n4nAI

Coding agents explained: how Claude Code and Devin work

A practitioner's breakdown of coding agents — what they are, how Claude Code and Devin operate under the hood, and what engineers get wrong about them.

n4n Team7 min read1,459 words

Audio narration

Coming soon — every post will get a voice note here.

A coding agent is an LLM-driven system that can read, write, and execute code in a persistent environment to complete multi-step programming tasks autonomously. Unlike chat assistants that respond to single prompts, coding agents maintain context across iterations, run tests, and iterate on their own output until a goal is satisfied. Claude Code and Devin are the two most prominent implementations, but they take fundamentally different architectural approaches.

What a coding agent actually is

At minimum, a coding agent needs four components: a language model for reasoning, a sandboxed execution environment, a tool interface for file operations and shell commands, and a control loop that feeds execution results back to the model. The agent receives a high-level objective — “add authentication to this API” — then plans, acts, observes, and replans in a cycle that continues until the task completes or hits a failure threshold.

This is distinct from an IDE copilot. Copilots are reactive: they wait for a cursor position or a highlighted block, then suggest a completion. Agents are proactive: they explore a codebase, identify relevant files, make coordinated changes across multiple files, run the test suite, and fix failures without further human input. The human sets the goal; the agent determines the steps.

How Claude Code works

Claude Code is Anthropic’s agent that runs in your terminal. It uses the same Claude 3.5 Sonnet model available via API, but wraps it in a thin CLI that grants the model direct access to your filesystem and shell. The architecture is deliberately minimal: the model sees your working directory structure, reads files you permit, and executes bash commands you authorize.

The control loop looks roughly like this:

# Simplified Claude Code control loop
while not task_complete and iterations < max_iterations:
    # Model receives: system prompt + conversation history + tool results
    response = model.complete(messages)
    
    # Parse tool calls from response
    for tool_call in response.tool_calls:
        if tool_call.name == "bash":
            result = subprocess.run(tool_call.args["command"], 
                                    capture_output=True, text=True, timeout=30)
        elif tool_call.name == "read":
            result = read_file(tool_call.args["path"])
        elif tool_call.name == "write":
            result = write_file(tool_call.args["path"], tool_call.args["content"])
        elif tool_call.name == "edit":
            result = apply_patch(tool_call.args["path"], tool_call.args["patch"])
        
        messages.append({"role": "tool", "content": result, "tool_call_id": tool_call.id})
    
    # Model decides next action based on tool results
    messages.append({"role": "assistant", "content": response.text})

Key design choices: Claude Code runs locally with your permissions. It doesn’t spin up a separate container — it operates in your actual project directory. This means it can use your existing tooling (npm, pytest, docker compose) without configuration, but it also means a buggy command can mutate your working tree. The model requests permission before destructive operations, but the boundary relies on the model’s judgment.

The system prompt encodes a specific workflow: explore first, then plan, then implement in small verifiable steps, run tests after each change. Anthropic tunes the model to favor grep and glob over reading entire directories, and to write focused patches rather than rewriting files wholesale.

How Devin works

Devin (from Cognition) takes a different approach: it runs in a cloud-hosted, fully isolated Linux container with a complete development environment preconfigured. You interact with it through a web UI or Slack, not your terminal. The container includes browsers, databases, and the ability to spin up preview deployments.

Devin’s control loop is more elaborate. It maintains a structured “knowledge base” of the codebase — not just file contents but inferred architecture, dependency graphs, and test patterns. Before writing code, it often spends iterations building this map:

# Devin-style exploration phase (conceptual)
def explore_codebase(goal: str) -> KnowledgeBase:
    kb = KnowledgeBase()
    
    # Phase 1: Broad structure
    kb.add("dir_tree", run("find . -type f -name '*.py' | head -200"))
    kb.add("entrypoints", run("grep -r 'def main\\|if __name__ == \"__main__\"' --include='*.py'"))
    
    # Phase 2: Goal-relevant areas
    keywords = extract_keywords(goal)
    for kw in keywords:
        kb.add(f"grep_{kw}", run(f"grep -r '{kw}' --include='*.py' -l"))
    
    # Phase 3: Deep reads of candidate files
    for file in kb.candidate_files:
        kb.add(f"file:{file}", read_file(file))
    
    return kb

Devin also implements explicit planning and verification phases. It writes a plan document, gets implicit approval by proceeding, then executes against that plan with checkpoints. If tests fail, it enters a debugging sub-loop with access to stack traces, logs, and the ability to add temporary instrumentation.

The container model means Devin can do things Claude Code cannot: spin up a staging database, run a full integration suite against a deployed preview, or debug a frontend by driving a headless browser. The tradeoff is latency (container provisioning, network round-trips) and isolation from your local tooling quirks.

Why the architecture differences matter

Claude Code’s local-first design optimizes for latency and fidelity to your environment. When you say “run the tests,” it runs your tests with your Python version and your local database. There’s no configuration drift. The feedback loop is tight: edit → test → edit takes seconds. This makes it excellent for focused refactoring, bug fixes, and feature work within a known codebase.

Devin’s cloud-container design optimizes for breadth and autonomy. It can onboard to an unfamiliar repository without your supervision, set up its own dependencies, and verify work in a clean environment that mirrors CI. It’s better suited for “here’s a repo, implement this feature from scratch” or “investigate this flaky test in the CI pipeline” — tasks where environment setup is part of the work.

Neither approach dominates. Most engineers will want both: a local agent for daily iteration, a cloud agent for async, environment-heavy tasks.

Concrete example: adding a rate limiter to an API

Suppose you have a FastAPI service and need to add per-client rate limiting with Redis backing. Here’s how each agent handles it.

Claude Code session:

> Add rate limiting to the /api/v1/ endpoints using Redis. 
  Use the existing redis client in app/core/redis.py. 
  Write tests.

# Agent explores
[reads app/core/redis.py, app/main.py, app/api/v1/router.py]
[reads tests/conftest.py, tests/test_api.py]

# Agent proposes plan
"I'll add a RateLimiter class in app/core/rate_limiter.py, 
 integrate it as middleware in main.py, and add tests."

# Agent implements
[writes app/core/rate_limiter.py]
[edits app/main.py to add middleware]
[writes tests/test_rate_limiter.py]

# Agent runs tests
pytest tests/test_rate_limiter.py -v
# 3 passed

# Agent runs full suite
pytest -x
# All 47 tests passed

Total time: ~3 minutes. The agent never left your terminal. It used your virtualenv, your Redis instance (running in docker-compose), your pytest config.

Devin session:

You paste the same request in the web UI. Devin:

  1. Provisions a container, clones the repo
  2. Runs pip install -e . and detects missing redis in requirements.txt
  3. Adds it, re-installs
  4. Discovers your docker-compose.yml, runs docker-compose up -d redis
  5. Performs the same exploration and implementation
  6. Runs tests in the container
  7. Spins up the FastAPI app with uvicorn app.main:app
  8. Hits endpoints with curl to verify rate limiting behavior manually
  9. Commits changes to a branch, opens a PR

Total time: ~12 minutes. The result is a PR you can review in GitHub, with CI already passing because Devin ran the same pipeline your CI runs.

Common misconceptions

“Agents just use more tokens”

Token count is a symptom, not the definition. A poorly designed agent burns tokens re-reading files it already saw, or thrashing between failed approaches. A well-designed agent spends tokens on exploration and verification — reading test output, checking git diffs, running linters. The token budget buys reliability. If your agent completes a task in 200k tokens that would take you 4 hours, the economics are favorable even at $3-15/M tokens.

“Agents replace code review”

Agents produce code that passes tests. They do not inherently produce code that matches your team’s architectural conventions, handles edge cases you haven’t specified, or avoids technical debt. You still review. The difference: you review a completed PR with passing CI, not a half-finished branch. The review shifts from “does this work?” to “is this the right design?”

“Agents need perfect prompts”

Prompting matters, but less than environment and tooling. An agent with a mediocre prompt but a fast, reliable test loop will outperform an agent with a perfect prompt but no way to verify its work. The control loop — act, observe, correct — is what makes an agent. Invest in the loop: fast tests, deterministic builds, clear error messages.

“Claude Code and Devin are the only options”

They’re the most visible commercial products. Open-source alternatives exist: Aider, OpenHands (formerly OpenDevin), SWE-agent, and custom loops built on LangGraph or raw API calls. The patterns are reproducible. If you control the environment and the model, you can build an agent tailored to your stack — one that knows your internal libraries, your deployment targets, your coding standards.

“Agents work best on greenfield projects”

Actually, agents excel in brownfield codebases if the codebase has good test coverage and modular structure. Greenfield work requires many architectural decisions that agents aren’t equipped to make. Brownfield work — “add this endpoint following the pattern in user.py” — is where the agent’s ability to read, pattern-match, and verify shines. The prerequisite is a codebase navigable by grep and readable by an LLM.

What to evaluate when choosing

If you’re deciding between Claude Code, Devin, or building your own, test these scenarios on your actual codebase:

  1. Onboarding: Give the agent a fresh clone and a task requiring environment setup (database migration, service dependencies). Measure time to first passing test.
  2. Debugging: Introduce a subtle bug (off-by-one, race condition, cache invalidation). Ask the agent to find and fix it. Measure iterations to root cause.
  3. Refactoring: Ask for a cross-cutting change (rename a core type, extract a service, migrate from sync to async). Measure files touched vs. files broken.
  4. Verification: After the agent claims success, run your full CI pipeline. Count false positives.

The agent that wins on your codebase with your tooling is the right one. Benchmarks on SWE-bench or HumanEval correlate weakly with real-world utility.

Where this fits in your workflow

Coding agents don’t replace the inner loop (write → test → debug). They compress the outer loop: “I need to implement this feature” → “feature is done and tested.” You still write the tricky algorithm, design the schema, decide the API shape. The agent handles the mechanical propagation: wiring the handler, adding the migration, updating the OpenAPI spec, writing the boilerplate tests, fixing the import cycles that result.

Treat the agent as a junior engineer who works instantly, never tires, but lacks judgment. Delegate the known-pattern work. Keep the novel-design work. Review the output. Ship.

Tagscoding-agentsclaude-codedevin

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All ai agents fundamentals posts →