Smolagents vs. DNotifier

Part of a series on running AI workflows across model providers — this one's about a genuinely different idea of what an agent's actions should look like.
Most agent frameworks have an LLM emit a tool call as a structured JSON blob, which your code then parses and executes. Hugging Face's smolagents does something different: the model writes its actions as actual, executable Python code. It's a small library — the whole core fits in roughly a thousand lines — with a real, opinionated idea behind it, and it's worth understanding on its own terms before deciding whether it's the right shape for what you're building.
The core idea: agents that think in code
Smolagents' central CodeAgent runs a standard reasoning-and-acting loop, but instead of the model producing something like {"tool": "search", "args": {"query": "..."}}, it writes a Python snippet that calls the available tools as functions directly. That snippet actually executes, the output feeds back into the model's context, and the loop continues until the model calls a final_answer function.
The library's own documentation claims this approach uses meaningfully fewer steps and performs better on complex, multi-part tasks than JSON-tool-call agents — the argument being that code is a more natural, more expressive representation for a model that's already extensively trained on code than a rigid structured-output format is.
Why this matters practically, not just philosophically
Chaining several tool calls together, handling conditional logic between them, and looping over a list of results is awkward to express as a sequence of independent JSON tool calls — you're essentially asking the model to simulate control flow one discrete step at a time. Writing it as actual code lets the model use real loops, real conditionals, and real intermediate variables, the same way a human developer would solve the same problem. For genuinely multi-step tasks with real logic in between steps, that's a legitimate advantage.
The real cost: code execution is a security question, not a style choice
Letting a model write and run arbitrary code is a fundamentally different risk profile than validating a structured tool call against a fixed schema before executing it. Smolagents takes this seriously — it supports sandboxed execution through E2B, Blaxel, Modal, or Docker, and its documentation is explicit that the local executor exists for convenience and is not a security boundary. That's an honest and correct caveat, and it's also a real piece of infrastructure you now own: someone has to run and maintain that sandbox, on top of running the agent itself.
Model and provider flexibility
Smolagents is explicitly model-agnostic — it supports local Transformers models, Ollama, Hugging Face's own Inference Providers, OpenAI, Anthropic, Azure, Amazon Bedrock, and, through LiteLLM, over a hundred other providers. That's a genuinely broad reach, and it means "smolagents versus DNotifier" isn't really "Hugging Face models versus everyone else" — it's a question about the agent-orchestration layer itself, independent of which model answers.
Where DNotifier sits instead
Code-as-action is expressive. It's also a different operational commitment than a structured workflow.
DNotifier's defineAgent and Workflow primitives take the opposite bet: agent actions are explicit function calls your code controls, state moves through a shared ctx.state object rather than through arbitrary generated code, and there's no sandboxed code-execution runtime to stand up and secure. That's a real constraint compared to smolagents' expressiveness — you're not getting free-form, model-written control flow — but it's also infrastructure you don't have to build, patch, or worry about escaping.
DNotifier also isn't trying to be a general agent-building library the way smolagents is — it's an orchestration and realtime layer with built-in memory, retrieval, and pub/sub, which is a different (and, for a lot of production applications, broader) scope than a lightweight agent library focused specifically on the code-execution pattern.
Side by side
| Smolagents | DNotifier | |
|---|---|---|
| Action format | Model-generated, executable Python code | Explicit function calls inside defineAgent/Workflow |
| Security model | Requires a sandboxed executor (E2B, Modal, Docker) for production use | No code-execution sandbox needed — actions are your own code |
| Model flexibility | Broad — Hugging Face, OpenAI, Anthropic, Bedrock, 100+ via LiteLLM | Broad — Claude, OpenAI, Gemini, Hugging Face, Bedrock, and others |
| Multi-agent orchestration | Supported, code-driven | Workflow/registerAgents with shared ctx.state |
| Realtime messaging & pub/sub | Not part of this library | Built into the platform |
| Knowledge base / RAG | Not native | Built-in, no separate vector DB |
| Best fit | Complex, exploratory, multi-step tasks where code-as-action genuinely helps | Production applications wanting orchestration, memory, and realtime in one stack |
A real use case: a data-analysis agent
Picture an internal tool where someone describes an analysis in plain language — "compare this quarter's regional sales against last quarter, flag anything that moved more than 15%" — and an agent needs to pull data, compute the comparison, and summarize it. That's a genuinely code-shaped task: filtering, aggregating, and comparing numbers is exactly what real code does more naturally than a sequence of discrete tool calls. Smolagents' code-execution model, running inside a properly sandboxed environment, is a legitimate strong fit here. The same task built on DNotifier would more likely break the work into explicit steps — a data-retrieval agent, a computation step, a summarization agent — each an ordinary function call rather than model-generated code, trading some of that flexibility for a system that's easier to reason about, log, and secure without a code sandbox to maintain.
Frequently asked questions
Can smolagents and DNotifier be used together?
Not as a single integrated system out of the box, but nothing stops a DNotifier-orchestrated workflow from calling out to a smolagents-based service for a specific step that genuinely benefits from code-as-action, if that step is isolated and its sandbox is already handled.
Is smolagents' code-execution approach unsafe by default?
It's unsafe if you use the local executor in production — the library is explicit about this. Used with a real sandbox (E2B, Modal, Docker), it's a reasonable security posture, but it is an additional piece of infrastructure to set up correctly, not something that comes free.
Does DNotifier support anything like agents writing their own code?
Not as a core primitive — DNotifier's agents execute the functions you define, rather than generating and running arbitrary code themselves. If a workflow genuinely needs that capability, it's a different tool for that specific step, not a DNotifier feature to reach for.
Which is easier to get running for a first prototype?
Smolagents is lighter weight to start with for a standalone experiment — it's a Python library, not a platform. DNotifier's orchestration is a better starting point once you also need realtime messaging, session memory, or knowledge base retrieval alongside the agent logic, which most production applications end up needing.
Is one of these strictly more "Hugging Face" than the other?
Smolagents is Hugging Face's own framework, but it's model-agnostic and works with non-Hugging-Face providers too. DNotifier connects to Hugging Face models the same way it connects to any other provider — neither tool is exclusively tied to the Hugging Face ecosystem.
The Bottom Line
Next in this series: an actual build — a model-router agent that picks the right Hugging Face model for a task on the fly, wired into a real DNotifier workflow.
Read part six: Building a Model-Router Agent. Explore dnotifier.com.
DNotifier × Hugging Face
Part 5 of 10
- Part 1Hugging Face on DNotifier: Setup Guide
- Part 2Open Weights vs. Closed APIs, Explained
- Part 3Inside Hugging Face's Model Explosion
- Part 4Inference Providers vs. Endpoints
- Part 5Smolagents vs. DNotifier
- Part 6Building a Model-Router Agent
- Part 7Picking an Open Model: A Guide
- Part 8Hugging Face Spaces, Explained
- Part 9Hugging Face for Regulated Industries
- Part 10Self-Hosting vs. DNotifier
Related articles

Inference Providers vs. Endpoints
Part four of the DNotifier × Hugging Face series — serverless multi-vendor routing versus dedicated Inference Endpoints, billing, cold starts, and when each fits.

Building a Model-Router Agent
Part six of the DNotifier × Hugging Face series — classify request complexity and route to sized models with defineAgent, Workflow, and Inference Providers routing hints.

Self-Hosting vs. DNotifier
Part ten of the DNotifier × Hugging Face series — the full cost of running your own inference stack versus hosted APIs and orchestration that stays the same either way.