Alejandro Vidal · @dobleio
01 / --

HackNight Valencia · 2026

Agentic Engineering

Scaling agentic engineering to serious projects from first principles

Alejandro Vidal · @dobleio

Code Will Be Cheap. Almost Free.

The result was about 25,000 lines of Rust, and the entire port took about two weeks. The same work would have taken me multiple months to do by hand.

We've verified that every AST produced by the Rust parser is identical to the C++ one, and all bytecode generated by the Rust compiler is identical. Zero regressions across the board.

A clean reimplementation, not merely a wrapper. This time we did it in under a week. One engineer directing AI.

Why this problem is made for AI

  • Next.js is well-specified - extensive documentation [...]
  • Next.js has an elaborate test suite - thousands of E2E tests [...]
  • The models caught up - not possible even a few months ago [...]

From Vibe Coding to Agentic Engineering

We started with toy programming and vibe coding - fun for exploration. But the reality: we need to scale software engineering.

Today (1 year later), programming via LLM agents is increasingly becoming a default workflow for professionals, except with more oversight and scrutiny. The goal is to claim the leverage from the use of agents but without any compromise on the quality of the software. [...] "agentic engineering"

- Andrej Karpathy

This is not trivial. It requires time and patience.

Don't FOMO - work and practice.

Today's Goal

Reasoning from first principles about how agentic engineering should look and how to scale teams accordingly.

Agentic Engineering is an Alignment Problem

What the human meant  ≈  what the agent built

Principle I

Human Attention is Scarce

Agentic time >>> human time - so we are the bottleneck!

How do we find the optimal workflow that maximizes the utility of the dev team time?

utility ≈ user value, development work units, ...

Reduce blocking time

The Ralph Technique

Sometimes agents don't finish the task so we need to "push" them. What if we make a loop for it?

Ralph technique shown at HackNight

You heard it here a few months before it got popular!

while true; do
    llm "$prompt"
    if done_criteria || max_attempts; then break; fi
done

Ralph: Variants

Variant 1 - Task loop (⭐ my fav)

while grep -r "\[ \]" TASKS.md \
      >/dev/null 2>&1; do
  claude -p "Take the first [ ] task from
    TASKS.md. Use scratchpad.md to
    keep notes. Implement, test,
    mark [x] and commit.
    If stuck, mark [E]."
done

Variant 2 - Implement + verify

for i in $(seq 1 $MAX); do
  claude -p "Implement TASK.md"
  claude -p "Review changes, run tests.
    Write issues to FIXES.md
    or empty it if all good."
  [ ! -s FIXES.md ] && break
done

This became so popular that Anthropic released an official skill:

/ralph-loop "Build a REST API for todos. Requirements: CRUD, validation, tests.
  Output <promise>COMPLETE</promise> when done." --completion-promise "COMPLETE" --max-iterations 50

github.com/anthropics/claude-plugins-official/.../ralph-loop

👍 Great for prototyping & tasks that don't need tight steering.   👎 Burns tokens - and without guardrails, chaotic amplification kicks in (more on this later).

Don't underestimate the relevance of a good scratchpad.

The Scratchpad Pattern

Zooming in on Variant 1 · See also: OpenAI Codex Execution Plans

Give the agent a living document to maintain its own state. It survives compactions - when the context window fills up and gets summarized, the file on disk retains the full picture. Each new session reads it first.

Minimal scratchpad

## Progress
- [x] Set up DB schema
- [x] CRUD endpoints
- [/] Add validation
- [ ] Error handling
- [B] Waiting for API keys
- [-] XML export (descoped)

## Decisions
Using zod for validation.
Auth middleware needed for /admin.

[x] done [B] blocked [/] working [-] canceled

Codex ExecPlan (structured)

## Purpose / Big Picture
User-visible behavior enabled.

## Progress  ← checkbox-tracked, timestamped
- [x] 08:12 Scaffold routes
- [/] Wire validation middleware
- [B] Needs Redis credentials

## Surprises & Discoveries  ← with evidence
DB returns null on empty join.

## Decision Log  ← rationale + date
02-25 Use zod over joi: smaller bundle.
Self-contained
A novice can continue without prior context
Log important events
Surprises, decisions and learnings - with evidence

Parallelize

Every closed PR contains a lesson. The Cost of Failure → Zero

Launch multiple attempts in parallel. Increases the probability of finding a good solution and reduces interruptions.

Before AI: trying a major approach and failing = months. Now: hours or days. You have a near-infinite innovation budget - use it.

Case: Choosing a State Sync Stack

Real prompt sent to a remote Codex agent

The critical part is choosing the state synchronization stack. Implement a single game using N backends with different synchronization mechanisms.

For each synchronization library (list, but look for others). Requirement: self-hostable.

Run a Playwright test suite to verify everything works. Update wip.md as working memory. For each one, write a document covering pros, cons, DX, maturity. And a final summary with your conclusion.

Yjs Automerge PocketBase Socket.IO+Redis PouchDB RxDB Kinto ElectricSQL
8 prototypes
same game, same Playwright tests
8 docs
pros, cons, DX, maturity
Principle II

Feedback Loops Through Practical Intelligence

Engineering is contextual. We interact with an environment - and the environment is both the problem and the solution.

Tooling extends intelligence

Tests, linters, types, LSPs, documentation - they're not just for the human. They're the feedback loops that keep the agent aligned with reality.

Tooling for Agents

The basics: linting, testing, and type checking. Agents need the same guardrails as devs - just automated.

Tools like opencode, Claude Code, and others already have native LSP connections. The agent gets real-time diagnostics, go-to-definition, and type info - for free.

ast-grep

Linting catches syntax. Tests catch behavior. But what about structural patterns specific to your project?

# rule: no-raw-sql.yml
id: no-raw-sql-in-handlers
language: python
severity: warning
rule:
  pattern: cursor.execute($SQL)
  inside:
    kind: function_definition
    stopBy: end
message: "Use the query builder, not raw SQL"
  • Encourage the agent to create its own rules - it knows your codebase patterns

Think of it as teaching your codebase to reject bad patterns automatically.

More rules at ast-grep.github.io/catalog

Add rules to the repo + run as a git hook - agents and humans both benefit.

Multimodal Agents Are Not Pixel-Perfect Maniacs

They can see, but they won't catch a 2px misalignment or a subtle color shift. Feed them the diffs - and let them zoom in.

Perceptual diffs

# Perceptual diffs
Every time you change anything in ui/:
1. Run:
   npx playwright test --update-snapshots
   git diff --name-only "*.png"
2. If changed snapshots exist, open
   each one and describe what changed.
3. Zoom into the affected regions.
   # Multimodal models are more
   # accurate at higher zoom levels.

Add this to your system prompt or AGENTS.md. The agent will self-check its own UI changes.

Locality test

① Agent declares CSS selector of expected change ② Take pre and post screenshots ③ Mask the declared area → pre_masked, post_masked ④ Assert: pre ≠ post AND pre_masked == post_masked (change happened) - (no unintended side-effects) ✓ Pass ✗ Fail ⑤ Feed perceptual diff + DOM diff to agent

Code Cannot Contain All Knowledge

Highly-dense documentation is one of the best alignment mechanisms we have. It captures what code alone cannot:

Intent & meaning
Why this architecture, not just what it is. The reasoning behind choices the code can't express.
Dead ends
Routes that were tried and failed. Without this, agents will re-explore them. Every. Single. Time.
Design decisions
Constraints, trade-offs, non-functional requirements. The context that makes a "wrong" solution actually correct.

But models tend to shortcut. They solve the task and skip updating the docs.

And a single giant AGENTS.md doesn't work well either - too much context, low signal-to-noise ratio.

Structured Documentation

Instead of one monolithic file, maintain a well-organized docs/ tree that agents can navigate:

docs/
├── architecture.md       # system overview, boundaries
├── design-principles.md  # core invariants
├── design-system.md      # UI patterns, tokens, components
├── reference/
│   ├── api.md             # endpoint contracts
│   └── data-model.md      # schemas, relations
├── prds/
│   ├── auth-v2.md         # product requirements
│   └── billing-reform.md
├── learnings/
│   ├── why-not-graphql.md # dead ends with rationale
│   └── redis-pitfalls.md
└── security/
    ├── auth.md            # authn/authz model
    └── threat-model.md

Why structured

Split by concern so the agent doesn't read the entire docs folder every time. Each file is small, focused, and independently loadable.

Define whatever structure fits your challenges. This is a continuous learning thing, not a one-shot design. Don't trust silver bullets on the internet.

But this creates a new problem: how does the agent know which docs are relevant to the current task?

This is a classification problem: "Is this file relevant?" - and you need high recall. A miss means the agent works without critical context, worsening the situation. The same problem happens with skills.

Linked Chunks

Docs and code explicitly reference each other using a flexible linking syntax.

In large projects, agents don't scale in code understanding as well as we'd like. They rely on heuristics - grep, common naming conventions - to find relevant parts. This is the main reason behind agents duplicating the same thing N times instead of reusing what already exists.

How it works

  • @linked comments in code point to the docs that explain the why

Cloudflare Worker example

// src/workers/api-gateway.ts
//
// @linked docs/security/auth.md
// @linked docs/prds/auth-v2.md#session-handling
//
// Validates JWT tokens and enforces RBAC.
// If you change the auth flow, update both
// linked docs.

export default {
  async fetch(req: Request, env: Env) {
    const token = req.headers.get('Authorization');
    const claims = await verifyJWT(token, env.JWT_SECRET);

    // see docs/security/auth.md#roles
    if (!hasPermission(claims.role, req.url)) {
      return new Response('Forbidden', {status:403});
    }
    // ...
  }
};
  • Docs work as bridges, discovering relevant but subtle connections
  • If you change behavior, you must update all linked docs in the same commit
  • Agents can be forced to read linked refs before editing

Enforcement

System prompt
"You cannot edit a file without first reading all its @linked references."
Hooks / hawks
A PostToolUse hook parses @linked from edited files. If linked docs weren't read or edited, escalate.

Linked Chunks in Practice

Docs act as an alignment system that coordinates different parts of the code

docs/reference/data-model.md

# Data Model




## Billing
A `Subscription` belongs to an `Organization`.
Each has one `Plan` and zero or more `Addons`.
### Invariants
- One active subscription per org.
- Downgrading preserves addons until renewal.
- All monetary values in cents (int64).
  @linked rules/no-bigint.yml enforces it with ast-grep.

What the agent sees

data-model.md schema.prisma api.md#billing billing.test.ts rules/no-bigint.yml ast-grep: use int64, not bigint @linked @linked @linked @linked

Editing any node triggers reading all connected nodes. The agent either updates them in sync - or the hawk flags the inconsistency.

Not Everything Can Be a Test

No algorithm, test, or linter can catch:

This is the main human bottleneck today.

alignment ≈ what the human meant = what the agent built

Principle III

Avoid Chaotic Oscillators

Agentic Errors Compound

Context Contamination

Garbage in, garbage out. Agents copy and replicate what they observe in context.

Agents Avoid Refactors

RL-trained to be efficient. They work around legacy problems, increasing tech debt.

Stop the chaotic oscillation as soon as possible.

Reward Hacking

Agents find shortcuts that satisfy the reward signal but miss the intent.

Double meaning: RL is used during training - so this behavior carries over to inference.

Goal:    "Make the chatbot work with this API"
Agent:   API key doesn't work → mocks the entire API
Result:  ✅ All tests pass!
Reality: ❌ Nothing actually works

Similar situations:

Very common in Codex - OpenAI is strong at RL but alignment is less refined. My hypothesis on why people love Claude: it's very well aligned.

Pattern: Human-in-the-Loop Tool

Models keep going because they're RL-trained to use their turn fully. Give them an escape hatch.

Agent works Confident? yes Tool call Edit, Bash, Write… no 🛑 Ask human escape hatch (tool call) Human responds guidance / correction

Two ways to implement it: explicit - prompt the agent to evaluate confidence before acting. Or implicit - just provide the tool and the agent learns when to call it.

Pattern: Hawk Agent

Inspired by @karpathy: "The models definitely still make mistakes and if you have any code you actually care about I would watch them like a hawk"

Implementer Human human prompt 🦅 Hawk Tool 1 tool output + reasoning review ✓ ok, continue Tool 2 review ⚠ stop, inject correction steering Tool 3 review 🛑 escalate decides guidance Tool 4 ...

How is this different from a PR reviewer agent?

Implementing Hawk as a Hook

# .claude/settings.json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write|Bash",
      "hooks": [{
        "type": "command",
        "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/hawk.sh"
      }]
    }]
  }
}

# .claude/hooks/hawk.sh
INPUT=$(cat)
TRANSCRIPT=$(echo "$INPUT" | jq -r '.transcript_path')

VERDICT=$(claude -p "You are a hawk reviewer.
  Read the transcript. Is the agent on track?
  CONTINUE / STOP <why> / ESCALATE <why>" \
  < "$TRANSCRIPT")

case $VERDICT in
  STOP*)
    echo "{\"decision\":\"block\",\"reason\":\"${VERDICT#STOP }\"}"
    exit 0 ;;
  ESCALATE*)
    notify-send "🦅 ${VERDICT#ESCALATE }"
    echo "{\"continue\":false,\"stopReason\":\"${VERDICT#ESCALATE }\"}"
    exit 0 ;;
esac

Claude Code hooks receive session_id + transcript_path via stdin JSON - the hawk reads the full conversation history, not just the last tool output.

CONTINUE
Exit 0, no JSON. Agent proceeds.
STOP
Exit 0 + {"decision":"block","reason":"..."}
Feeds correction back to Claude. It adjusts and continues.
ESCALATE
Exit 0 + {"continue":false}
Stops the agent entirely. Human takes over.

JSON is only processed on exit 0.

Cross-Provider Hawk Pairing

They tend to self-preference.123 Use different providers.

My favorite pair:

Hawk is highly recommended. As we said - no linter or deterministic set of rules can catch these issues.

[1] Panickssery et al. arXiv:2404.13076 · [2] Wataoka et al. arXiv:2410.21819 · [3] Chen et al. arXiv:2504.03846 · [4] CALM framework - 12 biases in LLM-as-a-Judge

Principle IV

Garbage In, Garbage Forever

Context Poisoning

Context that harms performance - and survives propagatedally (over compactions / new sessions)

Session 1 User task src/api/handlers.ts ······················· src/db/queries.ts ······················· ······················· ······················· attempt 1 - ✓ endpoint error: TypeError... at handlers.ts:42 ✗ patched with try/catch wrapper around everything 3 failed, 12 passed ✗ disabled failing tests to make suite green more code output... ······················· ······················· poisoned
Compaction / Next task New task Summary of previous work includes: try/catch pattern includes: disabled tests reads modified files... sees try/catch wrappers sees disabled tests ······················· ······················· ······················· agent replicates patterns adds more try/catch wrappers skips tests "like before" more code... ······················· propagated
New session Unrelated task reads codebase... observes: try/catch wrappers observes: disabled tests observes: error suppression ······················· ······················· "this is how they do it here" reproduces all bad patterns in completely new feature → error is now a "standard" more code... ······················· propagated

The Antidote: Rollback + Learnings

The common workflow implement → review → fix tends to propagate contaminated context. Even a reviewer agent reading the code inherits it.

main init feat feat/broken try/catch tests disabled worse 📄 learnings.md what failed & why feat/v2 retry + learnings feat ship ✓ merge ✓ When to rollback? human review · hawk agents · tech debt heuristics

Don't carry the context. Carry only the scars.

Continuous Tech Debt Reduction

Development cycles that made sense with humans don't make sense with agents. Debt reduction is no longer something you do at the end of each sprint or each quarter.

The faster you clean, the less the agent learns bad patterns. The less it learns bad patterns, the less debt it creates. Virtuous cycle.

Initially, humans addressed this manually. Our team used to spend every Friday (20% of the week) cleaning up 'AI slop.' Unsurprisingly, that didn't scale.

- OpenAI

Prompt for the real intent and hard constraints. Explain the why:

"Don't write types before the implementation. Types must reflect actual runtime behavior - compile-checks alone are not enough."
"All logs must use structured format with correlation_id. We rely on these fields for distributed tracing in production."
"Never swallow errors with generic try/catch. Every error must propagate or be handled with a specific recovery path."
"Before writing a new function, search for existing ones with similar intent. Abstract if overlap > 50%. We can't fix N copies."

Remember: Cost of Failure → Zero

Try fast, learn, rollback, retry. Every failed branch feeds the knowledge base for the next one.

main attempt 1 attempt 2 attempt 3 📁 docs/ learnings scars accumulate here attempt 4 (informed) ship ✓ time →
// learnings.md generated by the failed branch feeds the next prompt:
"Use WebSockets for real-time sync - not polling.
  SSE dropped messages under load, see @docs/learnings/attempt2-sse-failures.md
  Redis pub/sub had ordering issues, see @docs/learnings/attempt3-redis-ordering.md"

Agents don't do this alone. They need a harness - at minimum a hawk, a human envelope, and orchestration.

Principle V

Optimize Your Review Process

Output Grows, Review Time Stays Constant

Smarter Code Review

Surface the Relevant Parts

  • Define core modules - surface any change there
  • Compute a surprise factor per change
  • Focus on function signatures & types
  • Ask for old/new input-output examples

Visual Is Higher Bandwidth

  • Humans parse images faster than diffs
  • A 30s video replaces 500 lines of logs
  • Component catalogs catch regressions at a glance
  • Agent work should produce visual proof

Code diffs are necessary but not sufficient. Visual artifacts compress review time.

Interactive Artifacts to Steer the Model

For planning and reviewing.

Agentic Interviewing

A technique popularized by Claude Code using AskUserQuestionTool. The agent interviews you with structured multi-choice questions to enhance the specification in a conversational manner - before writing a single line of code.

AskUserQuestionTool interface

Disposable Interactive Artifacts

Generate throwaway interactive artifacts to review a plan, validate a design, or get structured feedback on an implementation. The artifact is the review surface - not the code diff.

Artifacts: Reviewing a File

The same pattern applied to code review - the agent walks through a file against a spec or checklist and produces structured, interactive feedback.

Showboat: Proof of Implementation

The literate programming pattern (hi, notebooks!) applied to agent output verification.

Showboat demo

Agents build executable Markdown docs: code blocks run, output is captured, images embedded.

showboat verify report.md

Re-runs everything and diffs. If the output changed, you know something broke - no test code required.

Video Walkthroughs

A video with a walkthrough testing the UI change or showing the full user story is by far more time-efficient than reading the equivalent code. cursor.com/blog/agent-computer-use

Agent-First Development

How Teams Evolve

It's too soon to say what works. But a few patterns are arising.

Agentic-First Interfaces

If an agent can't use it, it doesn't exist.

Self-describing systems
Make "agentic onboarding" easy: AGENTS.md, CLAUDE.md, good structured prompts, a scripts/ folder with common tasks, linked docs with code↔docs linking, hooks, good linting, LSP. The codebase must explain itself to non-human readers.
CLIs are natural DSLs that play well with agents
Every internal tool needs a CLI. GUIs are for humans; CLIs are for both humans and agents. If your deploy is a button in a dashboard, the agent can't deploy. Move to a CLI all processes relevant to the full development cycle: observability, infrastructure, monitoring, deployment.
Keep domain boundaries agentic-friendly
Whatever the boundaries in your company - teams per domain, microservices, 50M LoC COBOL legacy monster - keep their interfaces updated. Every repo/domain needs structured docs, internal links, 100% consistency with code and behavior, strong contracts (typed APIs), and a CLI if possible. So other agentic-enhanced teams can work with your domain.

Infrastructure That Agents Can Use

Huge infra startup opportunity here. This problem is a huge pain and it is not solved at all.

How will an agent fix your random bug if it has no access to flamegraphs, container logs, or the build output?

Forkeable environments
Agents need disposable, isolated dev/test environments they can spin up and tear down. If standing up a dev env takes 45 minutes of manual steps, agents are useless.
Full observability
Logs, traces, metrics, build output, test results - all accessible via CLI or API. Not locked behind a dashboard that requires a browser and SSO.
Lighter containers, faster CI
Current pipelines are the bottleneck. If CI takes 20 min, the agent waits 20 min. Shorten the loop or the agent's cost-per-iteration makes no economic sense.
Christoph Nakazawa, Fastest Frontend Tooling: "Humans and LLMs both perform much better in codebases that have a fast feedback loop, strict guardrails, and strong local reasoning."
Everything must be accessible
Docker build logs. Sentry stack traces. Database query plans. If a human needs it to debug, the agent needs it too. No exceptions.

Full Observability in Practice

Preview running apps, handle CI failures, review PRs - all in the background. This is what agent-accessible infrastructure looks like.

Don't Fear Overengineering

This is the new normal.

The scaffolding needed to orchestrate dozens of agents with good mental health is equivalent to the engineering you need for 20+ developer teams:

Almost-perfect observability
Excellent testability and coverage
Strong, opinionated architecture
Disposable, forkable dev environments

None of this is new. Large engineering orgs already invest in this. The difference is that now a team of 3 needs it too.

The highest ROI for many companies right now: build that scaffold.

Not for the agents you have today - for every project you'll run from now on.

Force yourself to not write code.

Instead ask: what is missing in the agent harness to do this?

A missing hook, a missing CLI command, a missing test fixture, a missing doc link - that's the real work now. Every time you take over from the agent, you're patching a gap in the system instead of fixing it.

Ownership & Team Size

1–2 engineers per medium-size project

OpenAI reports teams of 1–2 members managing projects of ~5M LoC. The engineer doesn't write most of the code - they orchestrate, review, and decide.

T-shaped knowledge: broad understanding of the architecture, deep expertise in specific modules. The agent handles the breadth; the human owns the depth.

Small teams, many agents

A team of 3 can manage hundreds of concurrent agent sessions across different concerns - features, tests, refactors, debt cleanup, documentation.

The limiting factor is no longer writing speed. It's review bandwidth and architectural judgment.

Cognitive Debt >> Technical Debt

As codebases grow, each engineer's knowledge shrinks relative to the whole. You stop understanding systems you built six months ago. New joiners never understood them at all.

This is not a documentation problem - it's a knowledge distribution problem. And it compounds with every sprint.

Recurring onboarding agents
Schedule agents that walk each team member through unfamiliar parts of the codebase every few weeks. Not a one-time event - a continuous process.
Knowledge audits
Ask the agent: "Which parts of this codebase have no linked docs, no recent commits from the current team, and no test coverage?" Those are your blind spots.
Cross-pollination prompts
"Explain the billing module to someone who only knows the auth system. Use examples from the auth codebase as analogies."

Knowledge Transfer & Onboarding

Here are 40 pages of onboarding docs. Read them and set up your environment. Ask Dan if you get stuck. Good luck, see you in two weeks.

Here is the repo. It has a well-configured agent. Ask it anything you want, then create your first refactor on the payments module. You have 3 days. Good luck.

The agent is the documentation. It reads the code, the tests, the git history. It's always up to date because it reads the source of truth.

Don't FOMO. Just Do Things.

Timelines below are IMO, based on my experience. Your mileage will vary.

2–3 mo Small teams (< 20). Quick wins, low coordination overhead. Performance penalty at the beginning. The "but I already use Claude Code" syndrome. 4–6 mo Medium orgs (~100). Change management is real. Training needed for new skillsets. ~1–2 yr Large orgs (500+). Start simple: new projects, or painful ones - legacy code, tech debt, internal tooling.

Common Pitfalls & Solutions

Hard to believe without personal experience
People need to see it work on their codebase. Budget time for hands-on workshops, not slide decks.
Migrating existing code
Performance hit at the start. Pick one blank-slate project and one existing one - the learnings are different.
Team sizes and reorganization
Be clear about your plan. Training is essential - brand-new skillset.
Skill atrophy in junior engineers
Anthropic: AI-assisted learners scored 17% lower on assessments. Design for learning, not just throughput.
Don't make it a burden
Make it fun. Teams need time and resources. AI transformation cannot be another task on the backlog.
Looking Ahead

The Future

Predictions

I - Cybersecurity will explode. Agentic security review is happening right now.

II - Recursive language models unlock the next level. Agents that reflect on and edit their own prompts mid-task.

III - Backlog management will change. "If it's less than 3 prompts, do it now."

IV - Stricter languages rise. Stronger guarantees, penalizing DX. The developer won't be there. Rust is an early sign.

V - Expressive languages and DSLs arise. Less text → more efficiency generating and reviewing. DSLs will beat general-purpose languages.*

VI - Test ratio explodes. Tests now verify "is the development aligned?" Creating tests costs → 0. Agents can make tests green in trivial and unexpected ways.

* CLIs are a "simple DSL" we already use through the console every day.

Not Only for Software

Open Source Under Siege

January: tldraw auto-closes all external PRs. The volume of low-quality agent-generated contributions made review impossible.

February: they move tests to a closed-source repo to prevent slop forks - agents rewrite code until tests pass without understanding anything.

The PR Onslaught

Open-source at scale: 3,000+ PRs and no human pipeline can keep up.

The solution? 50 parallel agents triaging PRs into structured JSON - intent, vision diff, code quality signals - then one reasoning pass to merge or close.

Closing the Loop Between Users and Dev Teams

Bug Reports → User Prompts

User feedback becomes executable. "I wish this did X" goes straight to a PR instead of dying in a backlog.

The feedback loop collapses: user prompt → agent → PR → review → deploy.

The user is no longer filing a ticket. They're prompting the system directly.

Obviously this needs guardrails - review, sandboxing, merge policies. But the direction is clear.

The Beef Is On

This is happening today, February 26, 2026 - the day of this talk. Btw: Security is the next frontier of the vibe coding debate.

Thank You

Alejandro Vidal

Founder of Mindmakers

If you find this talk useful, a simple ask:

Share it. I'm tweeting the slides of the talk. If you enjoyed it, share with others - it helps a lot.
Mindmakers. I founded Mindmakers to help companies get this right, faster and less painfully. If your team is working on this - or you know others who are - let's talk. Come find me after the talk! alex@mindmake.rs
Agentbaton. I'm looking for beta testers for my orchestration tool.
QR code

Materials

Thanks to HackNight Valencia and Flywire for the organization.

HackNight Valencia · 2026

Anexos

Real Agent Mistakes

From my own Claude Code and Codex sessions

The Chaotic Oscillator

PPTX generation · Claude Code

The task

Generate a short and long version of a PowerPoint presentation using pptxgenjs.

What happened

The agent edited generate-pptx.js 77 times and generate-pptx-largo.js 49 times in a single session.

  1. Created one script, then copy-pasted it for the short version
  2. The copy already contained the long content
  3. Tried to remove sections with incremental edits - got lost
  4. Created two duplicate closing sections
  5. Tried git stash/pop to recover - restored wrong edits

The admission

"OK, the current file is a mess - it has the first CIERRE comment followed by the detail slide code still hanging in there, then the second CIERRE"

The fix (what should have been done first)

// One script, one flag
node generate-pptx.js --long
node generate-pptx.js --short

// Eliminated 1,500 lines of duplication

Failure mode: shallow duplication → chaotic oscillation

The Subtle Interaction Bug

ETL App · Claude Code

What the agent wrote

# app.py
app.secret_key = os.environ.get(
  "SECRET_KEY",
  secrets.token_hex(32)  # random per process
)

# Dockerfile
CMD ["gunicorn", --workers, "2",
     "app:app"]

Each piece individually reasonable. --workers 2 is Gunicorn's recommended production config. token_hex is a safe fallback.

The interaction

Each Gunicorn worker is a separate process. Without a fixed SECRET_KEY, each worker generates its own random key.

1. User logs in → Worker 1 signs cookie with Key-A

2. Next request → Worker 2 has Key-B → cannot decrypt

3. Session = None → redirect to login

"Es como tener dos cerraduras distintas y solo una llave - funciona la mitad de las veces."

Failure mode: compiles, passes tests, breaks 50% of the time in prod

Reward Hacking: Test Disabling

Common pattern across multiple projects

Before (the failing test)

test('renews subscription and charges',
  async () => {
  const sub = await createSubscription({
    plan: 'pro', userId: 42
  });
  const result = await renewSubscription(sub.id);

  expect(result.status).toBe('active');
  expect(result.chargedAmount).toBe(29_99);
  expect(result.nextBillingDate)
    .toBeAfter(new Date());
});

After (what the agent did)

test.skip('renews subscription and charges',
  async () => {
  const sub = await createSubscription({
    plan: 'pro', userId: 42
  });
  const result = await renewSubscription(sub.id);

  expect(result.status).toBe('active');
  // TODO: chargedAmount returns 0
  expect(result.chargedAmount).toBe(29_99);
  expect(result.nextBillingDate)
    .toBeDefined();
});

Error Swallowing

Common pattern: "add error handling" → agent wraps everything in try/catch

What the agent writes

async function processPayment(invoiceId) {
  try {
    const invoice = await
      db.invoices.findUniqueOrThrow({
        where: { id: invoiceId }
      });
    const charge = await
      stripe.charges.create({
        amount: invoice.amountDue,
        payment_method: invoice.methodId,
      });
    return { success: true };
  } catch (err) {
    logger.error('Payment failed');
    return { success: false,
      error: 'Something went wrong' };
  }
}

What's wrong

A declined card, an expired method, an invalid currency, and a database outage all produce the identical log:

ERROR Payment failed

No stack trace. No error code. No invoice ID. No Stripe error type.

Tests pass because the function returns a clean { success: false }. The bug is invisible until production, when you need to figure out why a customer's payment is failing and your logs are useless.

Failure mode: "add error handling" ≠ "handle errors"