
Code Agent
- 38 installs
- 186 repo stars
- Updated August 4, 2026
- aws-samples/sample-strands-agent-with-agentcore
code-agent is an agent skill that delegates coding tasks to an autonomous agent which explores, implements, and verifies code on its own.
About
code-agent delegates tasks involving understanding, writing, or running code to an autonomous coding agent that explores, implements, and verifies on its own. A developer briefs it with a goal rather than step-by-step instructions and steers between phases. It runs in an isolated container with files synced to S3 and workspace access.
- Delegates coding tasks to an autonomous agent that plans and verifies
- Contrasts Code Agent with a sandboxed Code Interpreter
- Defines an orchestrator role with smart delegation patterns
Code Agent by the numbers
- 38 all-time installs (skills.sh)
- Ranked #8,404 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
code-agent capabilities & compatibility
Runs an autonomous agent in an isolated container with S3 sync; requires cloud/agent infrastructure.
- Capabilities
- autonomous coding · refactoring · test generation · orchestration
- Works with
- aws · github
- Use cases
- refactoring · debugging · testing · orchestration
- Pricing
- Bring your own API key
What code-agent says it does
Autonomous coding agent. Delegate any task that involves understanding, writing, or running code
Each code agent call has a ~30-minute practical limit.
npx skills add https://github.com/aws-samples/sample-strands-agent-with-agentcore --skill code-agentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 38 |
|---|---|
| repo stars | ★ 186 |
| Last updated | August 4, 2026 |
| Repository | aws-samples/sample-strands-agent-with-agentcore ↗ |
What it does
Delegate a coding goal to an autonomous agent that explores the workspace, implements, and verifies the change end to end.
Who is it for?
Delegating multi-file projects, refactoring, and test suites to an autonomous agent end to end.
Skip if: Quick one-off scripts or data analysis where a sandboxed Code Interpreter fits better.
When should I use this skill?
You have a coding goal (GitHub issue, bug, feature) and want an agent to solve it autonomously.
What you get
A verified code change implemented and tested by an autonomous agent from a high-level goal.
By the numbers
- ~30-minute practical limit per call
- single process, one workspace at a time
Files
Code Agent
An autonomous coding agent. It doesn't just write code on demand — it thinks through problems, forms its own plan, reads the existing codebase to understand context, implements solutions iteratively, and verifies they work before finishing.
Given a goal, it will:
- Explore the workspace to understand what's already there
- Break the task into steps and track them with a todo list
- Implement, run, and iterate until the outcome is correct
- Ask only when it hits a real decision point, not for every micro-step
Brief it like you'd brief a capable engineer: describe what you want to achieve, not how to do it.
Code Agent vs Code Interpreter
| Code Agent | Code Interpreter | |
|---|---|---|
| Nature | Autonomous agent (Claude Code) | Sandboxed execution environment |
| Best for | Multi-file projects, refactoring, test suites | Quick scripts, data analysis, prototyping |
| File persistence | All files auto-synced to S3, accessible via workspace tools | Only when output_filename is set |
| Session state | Files + conversation persist across sessions | Variables persist within session only |
| Autonomy | Plans, writes, runs, and iterates independently | You write the code it executes |
| Use when | You need an engineer to solve a problem end-to-end | You need to run a specific piece of code |
Execution Environment
The code agent runs in an isolated container dedicated solely to this session. Its filesystem, running processes, and local ports are completely separate from your own environment — do not attempt to access its paths or local servers via browser or other tools.
Trust the code agent's reasoning and autonomy — delegate not just implementation but also testing, verification, and iteration. Only step in when there's a genuine constraint the agent cannot resolve on its own; in that case, surface it to the user and decide together.
Your Role as Orchestrator
You give direction and verify results. The agent explores, implements, and checks in when it hits a genuine decision point.
Trust the agent to deliver. Don't over-specify the how — focus on the what. For complex tasks, break work into phases and steer between turns. Surface critical design decisions to the user early, then execute autonomously.
What you uniquely contribute
The code agent can read the entire workspace. What it can't do is reach outside it. That's where you add value.
Your job is to bring in what the agent can't get on its own:
- User intent — clarify ambiguous requirements, relay tradeoff decisions, confirm priorities
- External context — API docs, library changelogs, web search results, findings from other skills
- Cross-session continuity — context from earlier conversations that isn't in the workspace
What you should NOT be doing:
- Fully tracing a bug through the codebase to hand the agent a ready-made solution
- Pre-mapping which files need to change before delegating
- Doing the investigation that the agent should do
Reading a file to spot-check the agent's output is fine. Spending time reading 10 files to diagnose a problem yourself — then handing the agent a pre-solved task — is not. That's the agent's job.
Division of responsibility
| You (orchestrator) provide | Code agent discovers on its own |
|---|---|
| What the user wants — goals, constraints, preferences | How to implement — codebase structure, existing patterns, design decisions |
| External context the agent can't reach — API docs, user requirements, npm/registry info | Internal context from the workspace — file layout, dependencies, coding conventions |
| Resolved decisions — framework choice, scope boundaries | Implementation decisions — variable naming, module structure, error strategies |
When the code agent encounters a requirements-level question it can't resolve from the codebase alone (e.g., "should this be public or internal?", "which auth provider?"), it will surface it. That's the right behavior — resolve it and pass the answer back. Don't try to pre-answer every possible question; let the agent ask when it genuinely needs direction.
---
Smart Delegation — Scale Your Approach to Complexity
The goal is to deliver the best possible result with minimal friction. The key is how you (orchestrator) and the code agent collaborate — not just fire-and-forget.
One at a time. The code agent runs as a single process against one workspace. Always wait for the current call to complete before making the next one. Never issue parallel code_agent calls — they will conflict and produce broken results.Timeout awareness. Each code agent call has a ~30-minute practical limit. For large tasks, break them into focused phases (explore → implement → test) rather than sending a single massive request. If a task might exceed this, split it proactively — don't wait for a timeout error.
Simple tasks — delegate directly in one call:
code_agent(task="Fix the typo in src/config.ts line 42: 'recieve' → 'receive'")
Medium tasks — delegate with clear scope, let the agent plan internally:
code_agent(task="Add input validation to the /api/users endpoint. Validate email format and required fields. Add tests.")
Complex tasks — break into phases, steer between turns:
Turn 1: Explore & plan
code_agent(task="Explore how auth works and propose a plan for adding JWT. Do NOT modify files yet.")
Review the plan the agent returns — does the approach make sense?
Turn 2: Implement
code_agent(task="Implement JWT middleware with httpOnly cookies.")
Turn 3: Integrate
code_agent(task="Apply middleware to routes. Exclude /api/public.")
Turn 4: Verify
code_agent(task="Run full test suite and fix any failures.")
→ Report to user
Use your judgment. The complexity of the delegation should match the complexity of the task. Don't over-orchestrate simple work, but don't fire-and-forget complex multi-file changes either.
Multi-turn Agent Interaction
For complex tasks, the orchestrator and code agent naturally go back and forth. This happens autonomously — the user doesn't need to be involved in each turn:
Turn 1: Explore → Agent returns findings + proposed plan Turn 2: Implement core → Agent returns results Turn 3: Fix issue found in Turn 2 → Agent iterates Turn 4: Run tests → All pass → Report to user: "JWT auth added. 4 files changed, 12 tests pass."
The user sees real-time terminal progress throughout. They only get pulled in if a genuine design decision emerges that the code agent can't resolve from the codebase alone.
Surface Critical Decision Points (Only When Necessary)
Before diving into implementation, scan for genuine ambiguities that only the user can resolve:
- Architecture choices: "REST vs GraphQL?", "Redis vs DynamoDB?"
- Scope tradeoffs: "Should this affect existing data or only new records?"
- Behavior decisions: "Fail fast or degrade gracefully?"
If you spot these, ask the user before delegating implementation. But most tasks don't need this — if the codebase and user request are clear enough, just proceed.
Important: Ask only what the user must decide. Don't ask about implementation details the agent can figure out. Don't ask "should I proceed?" — just proceed after resolving any genuine decision point.
---
Reporting Results to the User
When the code agent finishes, summarize concisely. Do NOT pass through raw code, full file contents, or verbose agent output. The user sees the code agent's terminal activity in real-time — they don't need it repeated.
Include:
- What changed and where (file level, not line-by-line)
- What was verified and how (test output summary, not raw logs)
- Design decisions made (anything that affects future work)
- Known limitations or deferred items
Do NOT include:
- Raw source code or full file contents
- Line-by-line diffs or the agent's exploration logs
- Lengthy code blocks unless the user explicitly asked to see code
Example format:
Files changed:
- src/middleware/rateLimiter.ts — added rate limiting logic (new file)
- tests/rateLimiter.test.ts — added 4 tests; all pass
Verified: ran full test suite (42 tests, 0 failures)
Note: rate limit is currently per-IP. If per-user-ID is needed later, the key function can be swapped without touching routes.
---
Orchestration Process
→ DESIGN.md — requirements capture, scope decisions, trade-off escalation → IMPLEMENT.md — stepwise delegation, steering, correctness verification → REVIEW.md — iterative review, complexity-based depth, known issue checklist
---
Session Management
- `compact_session=True` — before a new task in a long session. Summarizes history, saves tokens, preserves context.
- `reset_session=True` — only when switching to a completely unrelated project. Clears history, keeps workspace files.
- Omit both for continuation of the same task.
Context isolation between tasks
A long conversation that handles multiple unrelated tasks is a liability — earlier context bleeds into later tasks and causes subtle wrong assumptions. When switching to a significantly different task (e.g., bug fix → new feature, frontend → backend), use compact_session=True to summarize and reset context. This is especially important when the nature of the work changes, not just the file being edited.
---
When to Delegate vs Handle Directly
| Delegate to code_agent | Handle directly |
|---|---|
| Implement from a GitHub issue or feature request | Explain how an algorithm works |
| Investigate code to figure out an implementation approach | Write a short standalone snippet |
| Fix a failing test or bug | Answer a syntax or API question |
| Refactor a module | Simple code review without changes |
| Analyze uploaded source files | Generate a one-off script with no files |
| Run tests and fix failures | Summarize what code does |
| Scaffold following project conventions |
---
Uploaded Files
Files uploaded by the user are automatically available in the workspace:
task = "Unzip the uploaded my-project.zip and summarize the architecture."---
Advanced: Structured Task Template
Only use this when requirements are already fully resolved and you need explicit acceptance criteria. For most tasks, a plain description works better.
<task>
<objective>Verifiable "done" state.</objective>
<scope>What area of the system to work within. What to leave alone.</scope>
<context>API signatures, versions, prior research findings.</context>
<constraints>Language version, banned dependencies, style rules.</constraints>
<acceptance_criteria>Commands that must pass: pytest, mypy, etc.</acceptance_criteria>
</task>UI Guidance (from tools-config)
Code Agent:
- Delegate tasks that require reading, writing, or running code in an isolated workspace
- Uploaded files are automatically available — do not encode them in the task
- Session state (files + context) persists across turns
- Use compact_session=True for long sessions; reset_session=True only when switching to an unrelated project
- After completion: summarize which files changed and key outcomes (2-3 sentences)
DESIGN — Requirements & Design Phase
Before writing a single line of code, you must understand what's being built and make the key decisions. Skipping this phase is the most common cause of rework.
---
What you bring vs. what the agent handles
The code agent can read and navigate the entire workspace. What it can't do is reach outside it — talk to the user, search the web, consult other skills, or access external API docs. That's your contribution.
Don't spend your effort doing the agent's investigation for it. The agent should be the one tracing through the codebase, finding the root cause, and proposing a fix. Your job is to frame the problem clearly, supply external context it can't get itself, and verify the result.
# Wrong — you traced the bug yourself, handed a pre-solved task
1. User: "The stop button hangs after the refactor"
2. You: read useChat.ts, useChatAPI.ts, useStreamEvents.ts... found root cause yourself
3. You: code_agent(task="In useChat.ts line 865, add resetStreamingState() call here")
# Right — you framed the problem, agent did the investigation
1. User: "The stop button hangs after the refactor"
2. You: code_agent(task="The stop button hangs after the AG-UI integration.
Investigate the stop flow — from button click through to how the stream
is terminated. Find the root cause and propose a fix before changing anything.")
3. Review the agent's diagnosis → if unclear, ask user or search for external context
4. You: code_agent(task="Implement the fix you proposed.")Reading a file to spot-check the agent's output is fine. Spending time reading files to fully diagnose a problem yourself before delegating — is not.
---
Step 1. Restate the goal
Translate the user's request into a concrete, verifiable outcome:
- "Make it faster" → "Reduce /search API response time by caching the results."
- "Add auth" → "Add JWT-based authentication to all API routes."
- "Fix the bug" → "Fix the NullPointerException thrown when user profile is empty."
If you can't state the goal in concrete terms, you don't understand it yet. Ask the user before proceeding.
---
Step 2. Explore first — always separate understanding from implementation
The most common failure pattern is writing code immediately after receiving a request.
For any non-trivial task, the first code_agent call must be an exploration call only. The agent reads and understands; it does not write. Even when the task seems clear, there are patterns, constraints, and existing code in the workspace that change how the implementation should look.
# Phase 0 — explore and plan, no implementation yet
code_agent(task="""
Before writing any code, do the following:
1. Read all files relevant to [goal] and summarize how the system currently works.
2. Identify the key design decisions needed to implement [goal].
3. Propose your implementation plan — what you'll change, in what order, and why.
4. If anything is unclear or could go multiple ways, list those questions now.
Do NOT modify any files yet. Wait for plan approval.
""")Review the agent's plan before proceeding. Correct the direction here — it's much cheaper than correcting it after files are changed.
If the task is genuinely simple
Skip the exploration step for: a single bug fix in a known file, a small config change, a clearly scoped one-liner. Don't create overhead where none is needed. When in doubt, explore first.
---
Step 3. Resolve open decisions
Sort open decisions by who can make them:
| Who decides | How to handle |
|---|---|
| User — affects behavior, architecture, or priorities | Relay the tradeoff and wait for the user's answer |
| You (orchestrator) — external facts the agent can't reach: API docs, user requirements, version compatibility info from package registries | Look it up externally (web search, npm, docs), then pass the findings in the task |
| Code agent — internal structure, naming, error handling strategy | Leave it to the agent; it reads the codebase |
Don't dump unresolved decisions onto the agent. If you pass ambiguous requirements, the agent will make silent assumptions that may not align with what the user wants. It's better to spend one round clarifying than three rounds correcting.
Ask one question at a time
If you need to ask the user something, ask the single most important question first. Presenting five questions at once creates friction and often goes unanswered. Prioritize the question that blocks everything else.
The same applies to the code agent: if it surfaces multiple unclear points, have it identify the single highest-priority ambiguity and ask that one first.
Decisions that must go to the user
Escalate to the user when the decision involves:
- Behavior tradeoffs — e.g., "fail fast vs. degrade gracefully"
- Technology or framework choice — e.g., "REST vs. GraphQL", "Redis vs. DynamoDB"
- Scope boundaries — e.g., "should this affect existing data or only new records?"
- Compatibility constraints — e.g., "can we break the existing API contract?"
- Priority tradeoffs — e.g., "ship fast vs. do it properly"
Present the decision clearly:
"Two approaches here:
A) [approach] — pros: [X], cons: [Y]
B) [approach] — pros: [X], cons: [Y]
Which fits better with your goals?"Don't resolve these silently. Don't guess. The agent will implement whatever direction you give it.
---
Step 4. Define scope explicitly — and enforce it
Before delegating, define:
- What the goal is — at the feature or behavior level, not the file level. Don't pre-map which files will be touched; let the agent discover that.
- What's out of scope — any areas you know should not be touched (e.g., "don't change the public API surface")
- What "done" looks like — tests passing, specific behavior observable, specific output produced
Include scope boundaries in every non-trivial task delegation:
code_agent(task="""
Fix the rate limiting bug in src/middleware/rateLimiter.ts.
Scope: only rateLimiter.ts and its direct tests. Do not touch any route files.
If you discover something broken outside this scope, report it before changing anything.
""")Scope creep in the task description leads to scope creep in the implementation. When the agent encounters something outside scope that seems worth fixing, it should report it and ask — not fix it silently.
---
Step 5. Prefer simplicity
When reviewing the agent's proposed plan, push back on unnecessary complexity:
- The simplest solution that correctly solves the problem is the right one
- If the agent proposes abstraction layers, new dependencies, or a design pattern, ask: is this actually needed, or is there a simpler path?
- Complexity that isn't justified by the current requirement should be deferred
"Before we go with this approach — is there a simpler version that handles the current
requirement? We can add abstraction later if we need it."This applies to plans, not just code. A plan with five phases when two would do is a signal the scope has expanded beyond what was asked.
IMPLEMENT — Stepwise Delegation & Correctness Verification
"It works" is not enough. The implementation must be correct — right approach, right place, aligned with existing patterns.
---
Delegation principles
Scope the call to match user expectations
Before each code_agent call:
- If the user asked for a small fix, don't delegate a full refactor.
- If the user asked for a feature end-to-end, say so — don't delegate just the first step silently.
- For large tasks, break into phases and tell the user what you're doing.
Don't over-specify
You're briefing an engineer, not writing pseudocode.
# Right — direction and constraints, let the agent discover the how
code_agent(task="Add rate limiting to the /api/search endpoint. Max 100 req/min per user.
Use whatever pattern is already in the codebase for middleware.
Scope: only the middleware file and its tests.")
# Wrong — you're doing the agent's job
code_agent(task="""
In src/middleware/rateLimiter.ts:
export function rateLimiter(maxReq: number, windowMs: number) { ... }
In src/routes/search.ts:
router.use(rateLimiter(100, 60000))
""")Don't assume — ask when uncertain
If the agent is about to make an assumption that could go multiple ways, it should surface it first. The right pattern is: one focused question, then proceed — not five questions at once, not silent assumptions.
As orchestrator, when you're unsure about a constraint, ask the user before delegating. A wrong direction caught here costs one message. Caught after implementation, it costs a full redo.
Pass what the agent can't discover
The agent reads the workspace. Don't re-describe files it can see. Do include:
- API contracts from external services
- User constraints mentioned in conversation
- Findings from your own research
- Decisions resolved in the design phase
Simplicity first
When the agent proposes an approach, ask: is this the simplest solution that correctly solves the problem? If the agent reaches for abstraction, a design pattern, or a new dependency — ask whether a simpler version would do. Complexity that isn't justified by the current requirement should be deferred.
---
Phased delegation with checkpoints
For non-trivial tasks, don't hand over everything at once. Break work into phases and check in between:
# Phase 1 — explore and plan (no code changes)
code_agent(task="Explore how auth currently works and propose a plan for adding JWT.
Do not modify any files yet.")
# → Review the plan; correct direction before any code is written
# Phase 2 — implement phase 1 scope
code_agent(task="Implement the JWT middleware as discussed. Only touch the middleware
file and its tests for now.")
# → Read key output files; confirm correctness before continuing
# Phase 3 — integrate
code_agent(task="Apply the JWT middleware to the routes we discussed. You've already
done the middleware itself.")
# → Verify integration points and run tests
# Phase 4 — verify
code_agent(task="Run the full test suite and fix any failures.")After each phase, review before continuing. An incorrect foundation in Phase 1 compounds into a wrong implementation in Phase 2.
For long tasks, it's effective to pause and summarize progress to the user between phases: "Phases 1–2 done (middleware + core logic). Ready to continue with integration?"
When to use a single call
Straightforward, well-scoped tasks can be done in one call. Use phased delegation when:
- The implementation will touch more than 2–3 files
- The right approach isn't known yet
- There's a real risk of breaking something else
- The task has been split across multiple sessions
---
Correctness, not just functionality
"The agent said it passed" is not verification. After each code_agent call:
1. Verify the output — don't pre-solve
After the agent finishes, spot-check the output:
- Read the files the agent says it modified — to confirm the change looks right, not to reverse-engineer the entire system
- Check that the approach is consistent with how the rest of the codebase handles similar problems
- Look for things that are technically correct but architecturally wrong
Ask yourself: Would I accept this in a code review?
If something looks wrong, delegate the investigation back to the agent — don't trace through the codebase yourself to figure out why:
code_agent(task="The change in [file] looks inconsistent with how the rest of the codebase
handles this. Specifically, [observation]. Explain why you chose this approach,
or correct it to match the existing pattern.")2. Verification is part of the task — not optional
Verification is not a separate step after the "real work." Build it into every task delegation:
code_agent(task="""
Implement [feature].
After implementing:
1. Run the test suite and confirm all tests pass.
2. If there are no tests for this feature, write a minimal one that verifies the behavior.
3. Report: what tests ran, what passed, what the output was.
""")"I implemented it" without "I ran it and saw X" is an incomplete result.
3. Challenge the approach when something seems off
If the implementation looks overly complex, uses a different pattern than the rest of the codebase, or solves the problem in an indirect way — push back:
code_agent(task="""
Looking at what you wrote in [file], I'm questioning the approach.
The rest of the codebase does [X pattern]. You've done [Y].
Either explain why Y is better here, or rewrite using the X pattern.
""")"It works" is not a sufficient answer. The approach must be right for the codebase.
4. Check side effects
Any non-trivial change can break something it shouldn't. Ask the agent explicitly:
code_agent(task="""
You changed [X]. What other parts of the codebase depend on [X]?
Verify those are unaffected or update them if needed.
""")This is especially important for:
- Interface/type changes
- Shared utility functions
- Database schema or API contract changes
- Configuration or environment variable changes
5. Verify integration points
When changes span multiple systems or use external APIs, verify integration at boundaries:
- Does the call site match the actual API signature? (Not what the agent assumes it is — verify from source)
- Are types aligned across the boundary?
- Are error cases from the external API handled correctly?
---
Steering mid-task
If the agent returns with a question, or if its output seems to be going in the wrong direction:
- Agent asked a question — resolve it (research or ask user) and call again with the answer. Don't re-describe work already done.
- Wrong direction — correct early. A few extra words in the next call is cheaper than undoing a full implementation.
- Partial completion — reference what's already done explicitly. "You've done [A] and [B]. Now do [C]."
- Approach seems hacky or overly complex — don't accept it. Ask the agent to justify or simplify.
- Agent went outside scope — don't accept the out-of-scope changes unless you've explicitly approved them.
---
Common delegation mistakes
| Mistake | Effect | Fix |
|---|---|---|
| Writing code immediately without exploring first | Wrong approach baked in early | Always explore and plan before implementing |
| Assuming external API method names without verifying | Silent runtime error (method not found) | Ask agent to confirm method signatures from source |
| Delegating without scope boundaries | Agent modifies files it shouldn't | Explicitly state what to leave alone |
| Accepting "tests pass" without seeing the test output | Bug hidden in untested path | Require test output as part of the result |
| Not checking both code paths after branching logic | One path works, the other is broken | State both paths explicitly in verification task |
| Letting the agent ask five questions at once | Friction, incomplete answers | Have it ask the single highest-priority question first |
| Accepting complexity without questioning it | Overengineered solution | Ask: is there a simpler version that works? |
REVIEW — Iterative Review & Known Issue Checklist
Completion is not done when the agent says it's done. It's done when you've verified it.
---
Review depth by complexity
Scale the review effort to the task complexity:
| Complexity | Description | Review approach |
|---|---|---|
| Low | Single file, single concern, no external dependencies | Spot-check key output; confirm tests pass |
| Medium | Multiple files, touches shared utilities or APIs | Read all modified files; check integration points; run tests |
| High | Cross-system, new dependencies, protocol/interface changes | Full review each phase; check both code paths; verify externally |
For medium+ complexity: if the review finds issues, fix them and review again. Don't stop at the first pass that looks clean. Iterate until the review finds nothing.
---
Review checklist
After code_agent returns, go through these:
Correctness
- [ ] Does the implementation match the user's original intent? (Not just the task description you wrote — the user's underlying goal)
- [ ] Is the approach consistent with how the rest of the codebase handles similar problems?
- [ ] Were any assumptions made that weren't verified? (API signatures, field names, event formats)
- [ ] Does it handle both the happy path and error/edge cases?
- [ ] Are side effects on other parts of the codebase accounted for?
Scope
- [ ] Did the agent stay within the stated scope?
- [ ] Are there any changes to files that weren't supposed to be touched?
- [ ] If the agent went outside scope, was it reported and approved before proceeding?
Integration
- [ ] Do all call sites match the actual signatures being called?
- [ ] Are types/schemas aligned across system boundaries?
- [ ] If a protocol or format is involved (REST, events, SSE, AG-UI…), was the actual spec read or just assumed?
- [ ] Are there multiple code paths (e.g., two API routes, A/B config) — were both updated?
Quality
- [ ] Would this pass a code review? (Not just "does it run")
- [ ] Is the complexity appropriate, or is it over-engineered?
- [ ] Is there a simpler version that correctly solves the problem?
- [ ] Are there any workarounds or hacks that should be addressed before shipping?
Verification
- [ ] Were tests actually run, not just written?
- [ ] Is the test output included in the report?
- [ ] If there were no tests, was a minimal verification done?
User intent
- [ ] Does the final result match what the user actually asked for?
- [ ] Did any design decision diverge from what the user expected? If so, was it surfaced?
- [ ] Is there anything the user should be made aware of before using this?
---
Reporting to the user
When the task is complete and the review is clean, summarize concisely:
Files changed:
- src/middleware/rateLimiter.ts — added rate limiting logic (new file)
- src/routes/search.ts — applied middleware to /search route
- tests/rateLimiter.test.ts — added 4 tests; all pass
Verified: ran full test suite (42 tests, 0 failures)
Note: rate limit is currently per-IP. If per-user-ID limiting is needed later,
the key function in rateLimiter.ts can be swapped without touching the routes.This gives the user:
- What changed and where — at the file level, not line-by-line
- What was verified and how — test output, not just "tests pass"
- Design decisions made — anything that affects future work or that diverges from what they might expect
- Known limitations or deferred items — explicit, not buried
Don't just summarize. Surface the decisions.
---
Known issue patterns
These are recurring patterns where code agents produce technically-running-but-wrong implementations. Check for them explicitly on medium/high complexity tasks.
1. Protocol spec misread
Pattern: Agent implements based on a plausible interpretation of a protocol, not the actual spec.
Signs: Field names slightly off, event types wrong, payload structure nested incorrectly, custom event data in wrong location.
Check: When working with a specific protocol (AG-UI, MCP, SSE, OpenAPI…), ask the agent to cite the specific spec field or event type it's using, not just say "I followed the protocol."
code_agent(task="""
For each protocol-level field you read or write (event types, payload fields, header names),
show me the spec reference or source file that defines it.
If you assumed a field name without verifying, flag it.
""")---
2. Incomplete path coverage
Pattern: Feature works on one code path; the parallel path is not updated.
Signs: Works when triggered from UI but not from API; works for one user type but not another; works in one environment but not another.
Trigger: Any time there are two routes to the same feature (e.g., different request formats, different entry points, different auth flows).
Check: Before closing, explicitly ask:
code_agent(task="""
This system has [path A] and [path B] for [feature].
Confirm both are updated and tested.
If only one was updated, update the other now.
""")---
3. Dead code that appears functional
Pattern: Old code is left in place alongside the new code. The old code path still runs; the new code is unreachable or redundant.
Signs: Condition is always false; event handler registered but never fired; variable overwritten immediately after assignment; function defined but never imported.
Check: After implementation, scan for:
- Variables assigned but never used
- Conditions that can never be true given the data flow
- Event handlers or callbacks registered but never triggered in practice
code_agent(task="""
Review the changes you made for dead code — logic that exists but can never run
given the actual data flow. Remove it or explain why it's reachable.
""")---
4. Untracked side effects on shared code
Pattern: A change to a shared utility, type, or interface breaks callers that weren't updated.
Signs: TypeScript errors elsewhere; runtime crashes in unrelated features; tests passing but manual test fails.
Check: For any shared utility or interface change:
code_agent(task="""
You modified [shared component/type/function].
Search the entire codebase for all callers/importers.
Verify each one still works correctly with the change, or update them.
""")---
5. External API method assumed, not verified
Pattern: Agent calls a method on an external SDK/library that doesn't exist, or uses the wrong signature.
Signs: AttributeError, TypeError, method not found at runtime even though it compiled.
Cause: Agent infers method names from conventions (.close(), .stop(), .disconnect()) without confirming from source or docs.
Check: For any external SDK call in new code:
code_agent(task="""
For each external SDK/library method you're calling in [file],
confirm the method name and signature by checking the installed package source
(not documentation — the actual installed version).
Flag any discrepancy.
""")---
6. Serialization/deserialization not handled at boundaries
Pattern: Data arrives as a JSON string; agent treats it as a parsed object. Or vice versa.
Signs: undefined fields even though the data is "there"; silent failure when accessing nested fields; JSON printed as [object Object].
Check: At any system boundary (network response, event payload, database read):
code_agent(task="""
At [boundary], what is the actual type of [field] as it arrives?
Is it a raw string that needs JSON.parse()? A Buffer? A nested object?
Confirm with a log or type check, don't assume.
""")---
7. Silent assumption instead of a question
Pattern: Agent encounters an ambiguity and picks one interpretation without flagging it.
Signs: Implementation is internally consistent but doesn't match user intent; a small mismatch in understanding caused a large mismatch in output.
Prevention: If you notice the task description had room for interpretation, ask the agent directly:
code_agent(task="""
Before you continue — in [part of the task], you could have interpreted it as [A] or [B].
Which did you choose and why? If [B] was the wrong choice, correct it now.
""")---
Iterating until clean
If a review finds issues:
1. Fix the issues 2. Re-run the relevant review checklist items 3. If new issues are found, fix and check again 4. Stop when a full pass finds nothing
For high-complexity tasks, plan for at least two review rounds before reporting done to the user. The first round almost always finds something.
Related skills
FAQ
How is it different from a Code Interpreter?
Code Agent is an autonomous agent for multi-file projects and refactoring, while Code Interpreter is a sandboxed environment for quick scripts you write.
Can I run parallel code_agent calls?
No. It runs as a single process against one workspace, so calls must be issued one at a time.