Code Agents: Actions as Code

The single idea that defines smolagents is that an agent's action is a snippet of Python, not a JSON blob. It sounds like a minor encoding detail and turns out to change what an agent can do in a single step — because code carries logic, loops, variables, and composition that structured tool calls simply can't express.

The last post introduced the code agent as smolagents’s signature. This post goes deep on it: what a code action actually is, how it differs from JSON tool calling, and why expressing actions as code is more than a formatting choice. Understanding the code agent is understanding smolagents, because everything else in the library serves this one idea.

Two ways for an agent to act

When an agent decides to do something — call a tool — that decision has to be expressed in some format the framework can execute. There are two approaches, and the difference is the whole point of smolagents:

JSON tool call (one action = one tool call):
  { "tool": "search", "args": { "query": "largest EU cities" } }
  → framework runs search, returns result, model decides next call

Code action (one action = a code snippet):
  cities = search("largest EU cities")
  populations = [get_population(c) for c in cities[:3]]
  answer = sum(populations)
  → framework runs the whole snippet: search, loop, three get_population calls, a sum

Look at what the code action did in one step: a search, a loop over its results, three more tool calls, and a computation. In the JSON approach, that’s many separate round-trips — call search, get result, call get_population, get result, call again, again, then sum — each a separate model turn. The code agent collapses all of it into a single action. That’s the crux of why code actions are powerful.

Why code is more expressive

The deeper reason code actions matter is expressiveness: code can naturally express things JSON tool calls express awkwardly or not at all. A JSON tool call is, fundamentally, “invoke one function with these arguments” — it has no native way to represent:

The insight is that real tasks are usually more than a sequence of isolated function calls — they involve looping, branching, combining results, and computing, which is exactly what a programming language expresses and a JSON schema doesn’t. So code actions aren’t just a different encoding; they let the agent express richer actions that match the actual shape of the work. An agent that can write code can, in a single action, do what a JSON-tool-calling agent needs many turns to accomplish — because code is a fuller language for “what to do” than a list of function calls.

Why it plays to the model’s strengths

There’s a second argument, about the model: LLMs are trained on enormous amounts of code, so writing code is something they’re often exceptionally good at — arguably more natural for them than emitting a specific, rigid JSON schema. The code agent leans into this:

So code actions align the agent’s action language with what LLMs are strongest at, which is part of why the approach performs well (the next post covers the measured efficiency gains). Rather than forcing the model into a constrained JSON format for each isolated call, you let it write code — a language it knows deeply and can use to express rich, composed actions. This is the elegant core of smolagents’s bet: the best way for a code-fluent model to act is by writing code.

Code agents vs tool-calling agents in smolagents

smolagents supports both approaches (it has a code agent and a tool-calling agent), and knowing when each fits is practical:

smolagents primarily emphasizes code agents because they perform better overall on substantive tasks, but offers tool-calling agents for the simple cases (and for constrained environments). The guidance: default to code agents for real work, and use tool-calling agents for simple flows or where code execution isn’t safe. The next post quantifies why code agents win — the efficiency and accuracy evidence — and then the security post covers the cost that comes with executing code.

Key takeaways

Further reading

Sources & References