DM Explains · No. 006 · Orchestration
Pluggable orchestration: why AI agents are becoming swappable parts
Docker Agent and 10xScale Agentflow treat the model, tools, memory and routing logic as separate slots you can swap, not one script you rewrite. Here is how the config actually holds it together.
· 14 min read

Read me first
Pluggable orchestration genuinely does let you swap the model, the tools or the routing logic without rewriting an agent's core, but only because every part is written down in a config or graph, not because the wiring disappears.
A three-agent Docker Agent workflow: generator drafts content declaratively in YAML → model layer lets it call OpenAI or Bedrock → registry gives it local and MCP tools → workflow engine chains generator → translator → publisher → sequential decision: each waits for the prior to finish → state layer persists drafts in Postgres → whole workflow packaged as an OCI image, pushed and pulled to run anywhere, each agent swappable independently.
A team ships a chatbot with OpenAI wired directly into the code. It works, so nobody touches it — until six months later, when someone wants to try Anthropic for one task and add a translator step before publishing. They open the file and find the model name, the tool calls and the hand-off logic all tangled into one script. Changing any one of them risks breaking the rest.
That is the ordinary shape of a hard-wired agent: fast to build, expensive to change. Pluggable orchestration is the opposite bet — slower to set up, cheap to change, because the model, the tools, the memory and the routing between agents are each a separate slot rather than a line buried in a function.
Everyday picture. Amma keeps a shared house binder listing who handles which chore — Papa does groceries, Dadi does the school pickup, Arjun walks the dog. Any name can be swapped into a role by rewriting one line in the binder, without rewriting the whole week's plan.
Where the picture breaks. The binder is fixed once written for the day. A live orchestration graph can route dynamically mid-task, looping back or switching mid-stream in ways the paper binder never does.
Why it exists now
The problem is not new — teams have always wanted to change models or tools without rewriting an agent. What changed is that two frameworks made the pattern explicit and runnable rather than a private convention. Docker released Docker Agent, which lets a developer describe an agent's model, personality, tools and teammates in a YAML file and run it with one command, treating an agent the way Docker has always treated a container. In parallel, 10xScale Agentflow built the same idea in Python, with a lightweight Agent class, a graph engine inspired by LangGraph, and native support for event publishing and human approval steps.
Neither framework automates orchestration away. Both push more decisions into an explicit, versionable file — a YAML document or a compiled graph — than a hand-rolled script ever had. The flexibility comes from writing the wiring down plainly, not from hiding it.
How it works
Declarative definition
Write the plan once, in a file anyone can read and change
What it is. Instead of writing custom glue code for each piece of an agent, the developer writes a YAML file (Docker Agent) or an Agent class (Agentflow) describing the model, personality, tools and teammates.
Why it exists. A description that sits apart from the execution code can be versioned, diffed and shared, and it is the entry point for swapping any single component without touching the rest.
Where it breaks. A YAML file cannot express dynamic, runtime-only decisions — it describes the plan, not every branch a live run might take.
How that's handled. The graph engine underneath (see step 4) handles the runtime branching; the declarative file only sets the starting configuration.
In technical terms
In technical terms: Docker Agent's YAML config declares model, tools and sub-agents and is run with a single command; 10xScale Agentflow's Agent class can build a complete agent in roughly 10-30 lines of code as of v0.5.3.
Model-agnostic layer
The provider is a slot, not a dependency
What it is. The runtime routes model calls to whichever provider is configured, rather than the agent code calling one SDK directly.
Why it exists. Cost, capability or availability reasons routinely push teams to change providers; if the provider is a slot rather than a fixed dependency, that change happens in config.
Where it breaks. Provider-specific quirks — tool-call formats, context limits — still leak through. Swapping providers is not always a drop-in no-op.
How that's handled. The framework absorbs the common surface (chat, tool calls) and leaves provider-specific edge cases to be tested per swap, not assumed away.
In technical terms
In technical terms: Docker Agent routes to OpenAI, Anthropic, Gemini, AWS Bedrock, Mistral, xAI or Docker Model Runner; Agentflow calls native SDKs from OpenAI, Google Gemini or Anthropic, or any other provider.
Tool and MCP registry
One ledger, many shelves of tools
What it is. A single registry receives tool-call requests and dispatches them to whatever actually implements the tool — a local function, a remote server, an integration.
Why it exists. Treating tools as registry entries, rather than inline function calls, means adding or removing a capability is an edit to the registry, not a change to the orchestration graph.
Where it breaks. A registry entry only runs what it is given; it cannot notice that a tool is subtly wrong for the task the way a person reviewing the plan might.
How that's handled. Parallel execution keeps unrelated tool calls from queuing behind each other, but choosing the right tool is still a design decision, not something the registry checks for you.
In technical terms
In technical terms: Agentflow's ToolNode is a unified registry and executor supporting local Python functions, Model Context Protocol (MCP) servers, Composio integrations and LangChain tools, running them in parallel by default.
Graph or workflow engine
Edit the wiring, not the workers
What it is. A directed graph of nodes and edges describes what runs, in what order, and under what condition — compiled once, then executed.
Why it exists. The compiled graph is the single point that manages state loading, routing, checkpointing and shutdown, so changing behaviour means editing the wiring rather than the code inside any one node.
Where it breaks. A compiled sequential workflow cannot suddenly run its steps concurrently; the shape of the graph has to match the real dependency between steps, or it stalls.
How that's handled. Docker Agent's workflow type chains named agents — a generator, then a translator, then a publisher — so each one completes before the next starts, matching a genuinely sequential dependency.
In technical terms
In technical terms: Agentflow's StateGraph compiles nodes and edges and manages state loading, routing, checkpointing and shutdown automatically; Docker Agent's workflow feature chains named agents such as generator, translator and publisher.
Sequential or parallel?
Block and wait, or split and run together
generator → translator → publisher workflow: generator finishes → 1 asks if translator needs one task or several → single translation task → 2 sub_agents blocks parent until translator returns → 3 (alternatively) translator could hand off directly to publisher, staying in one session → 4 if publisher needed to post to five channels at once, background_agents would run them in parallel → 5 translator's output merges back into the graph → publisher posts, each agent swapped without touching the others
What it is. A choice between three multi-agent topologies: hierarchical delegation, peer-to-peer handoff, or independent background tasks.
Why it exists. Not every multi-agent problem has the same shape. A specialist sub-task wants delegation; a conversation that shifts speaker wants a handoff; several unrelated jobs want to run at once.
Where it breaks. Using the blocking delegation tool for tasks that should run concurrently causes needless waiting — Docker Agent's own documentation says as much.
How that's handled. Docker Agent separates the three patterns into different tools rather than one, so the choice is explicit at config time.
In technical terms
In technical terms: Docker Agent's sub_agents pattern uses a transfer_task tool where the parent blocks until the child finishes; handoffs keep one session while the active agent switches, even looping A to B to C to A; a separate background_agents toolset is intended for independent tasks that run at the same time.
State and memory layer
Memory as a backend you choose, not a hope
What it is. The record of what has happened so far in a run, persisted through a backend that can be swapped rather than a variable held in process memory.
Why it exists. A graph that runs once in a demo and a graph that runs for days in production need different persistence guarantees; making memory a pluggable backend lets the same graph serve both.
Where it breaks. Swapping memory backends can change latency and consistency guarantees. An in-memory checkpointer used in development will not behave the same under production load.
How that's handled. Context is trimmed only at iteration boundaries, never mid-execution, so a run in progress is never cut off half-way through a step.
In technical terms
In technical terms: Agentflow persists state via in-memory or PostgreSQL+Redis checkpointers, on top of a 3-layer memory model combining a Redis cache, Postgres and a vector store, merging each node's update back into shared state through reducers.
Packaging as OCI images
An agent becomes something you can push, pull and reuse
What it is. A finished agent — model config, tools, sub-agent team — packaged as an artefact that can be pushed to and pulled from a registry, the same distribution model used for container images.
Why it exists. It extends "pluggable" from individual components to whole agents, so a complete orchestration setup can be shared and run elsewhere without rebuilding it.
Where it breaks. Packaging an agent does not package its external state. Secrets, live memory or connected data sources still need separate handling wherever the image is pulled.
How that's handled. The image carries the declarative config; the operator still wires in credentials and live data at run time.
In technical terms
In technical terms: Docker Agent allows a packaged agent to be pushed to and pulled from any OCI (Open Container Initiative) registry.
Compared with what came before
| Hard-wired script | Pluggable orchestration | |
|---|---|---|
| Model choice | Fixed SDK call in code | Config slot, swapped by editing a line |
| Adding a tool | New function wired by hand | New entry in a shared registry |
| Multi-agent routing | Custom if/else logic | Named pattern: delegation, handoff or background |
| Changing behaviour | Edit the code that runs the task | Edit the graph or config that wires the task |
| Sharing the setup | Copy the whole codebase | Push and pull a packaged config or image |
| What you give up | Simplicity of one file, no extra layer | Total control over every line of glue code |
The judgement is not that hard-wired scripts are wrong. A single-shot prompt with no tool use gains nothing from a graph engine and a registry — it is overhead in search of a problem. The trade only pays off once there is more than one moving part worth changing independently: more than one provider under consideration, more than one tool, more than one agent in the loop.
Where it breaks
Pluggable orchestration removes the cost of swapping a component, but it does not remove the cost of getting the topology wrong in the first place, and it is not a security boundary or a correctness guarantee.
Blocking delegation is the wrong tool for many tasks at once
Docker Agent's own documentation is explicit that its sequential transfer_task tool blocks the coordinator until the sub-agent finishes, and directs anyone with several independent tasks toward the separate background_agents toolset instead. Choosing the wrong pattern here does not fail loudly — it just makes the whole run slower than it needed to be.
A packaged agent, pushed to a registry, carries its declarative config but not its external state: secrets, live memory, connected data sources all still have to be wired in wherever the image lands. A registry of tools only runs what it is told to run; nothing in the registry checks whether a tool was the right choice for the task at hand — that judgement still sits with whoever wrote the config. And a graph compiled for a sequential dependency, like generator feeding translator feeding publisher, cannot be made to run those steps in parallel just by wanting it to; the shape of the graph has to match the real shape of the work.
Numbers to carry
| Fact | Detail |
|---|---|
| Agentflow Agent class size | Roughly 10-30 lines of code, as of v0.5.3 |
| Docker Agent providers | OpenAI, Anthropic, Gemini, AWS Bedrock, Mistral, xAI, Docker Model Runner |
| Agentflow provider SDKs | OpenAI, Google Gemini, Anthropic, or any other provider |
| Agentflow tool sources | Local Python functions, MCP servers, Composio integrations, LangChain tools |
| Agentflow persistence options | In-memory checkpointer, or PostgreSQL+Redis checkpointer |
| Agentflow memory layers | 3 layers: Redis cache, Postgres, vector store |
| Docker Agent packaging | Any OCI registry, push and pull |
| Docker Agent workflow example | Generator → translator → publisher, sequential |
Myths worth killing
| Commonly repeated | What is actually true |
|---|---|
| "Pluggable means less configuration" | The framework pushes more decisions into an explicit, versionable YAML file or graph than a hand-rolled script ever had — flexibility comes from being declarative, not from being automatic. |
| "Agentflow is LangGraph" | Agentflow describes itself as LangGraph-inspired, and borrows the nodes-and-edges vocabulary, but it is a separate framework with its own graph engine, command-line tool and client. |
| "Delegation and handoff are the same pattern" | Delegation (sub_agents) blocks the parent until a child task finishes; handoffs switch the active agent while keeping one session, and can loop between agents — they are different topologies for different jobs. |
| "Packaging an agent packages everything it needs" | The OCI image carries the declarative config, not secrets, live memory, or connected data sources — those still need separate handling wherever the image runs. |
| "More agents means more parallelism automatically" | Docker Agent's sequential delegation tool blocks by design; running tasks in parallel requires deliberately choosing the background_agents pattern instead. |
Worked example
The generator → translator → publisher workflow, walked through as Docker Agent's own workflow pull request describes it:
- A developer writes a YAML file naming three agents — generator, translator, publisher — and lists them in sequence under the workflow type.
- The generator agent drafts content using whichever model provider is configured for it, without knowing anything about translation or publishing.
- The workflow engine waits for the generator to finish, then hands its output to the translator agent, matching the documented pattern where each named agent completes before the next starts.
- The translator agent converts the draft, using its own configured model — which could be a different provider from the generator's, since the model is a slot, not a hard dependency.
- The publisher agent receives the translated text and posts it, again through its own tool configuration.
- A team member later decides to try a different provider for translation only. They edit the model field for the translator agent in the YAML file — illustrative, but this is the shape of the change: one line, not a rewritten script.
- The whole config, unchanged in its generator and publisher parts, can then be pushed to an OCI registry so another team can pull and run the same three-agent pipeline without rebuilding it.
Should you use it?
Reach for pluggable orchestration when more than one provider is genuinely on the table, when more than one tool needs to be added or removed over the agent's life, or when the task naturally splits into specialist sub-agents that need to delegate or hand off work. It also earns its keep when the setup needs to be shared as a versioned artefact rather than copied as a codebase.
Skip it for a one-shot prompt with no tool use, for ultra-low-latency inline function calling where an extra runtime layer is unwelcome, or for a project where a single tightly coupled codebase is genuinely fine because nothing about it needs to change independently.
The cheapest first experiment is not a rebuild: take one existing agent's model call and move it into a declarative config file, without touching the tool logic yet, and confirm that swapping the provider there does not require touching anything else.
Say it in the room
"Use it when you expect to swap the model, the tools or the routing more than once; skip it for a single prompt with no moving parts to swap."
Lines to carry
- "Flexible because it is written down, not because it is invisible."
- "The graph is the one thing you edit to change behaviour."
- "A slot, not a dependency."
- "Blocking is fine for one task; it is the wrong tool for many at once."
- "Package the agent, not just the answer."
FAQ
Is Docker Agent the same thing as a Docker container?
No. Docker Agent uses container-style packaging — OCI registries, a YAML config format — for AI agents specifically. It drives a loop between a model, its tools and its sub-agents; it does not schedule general application containers the way Docker Compose or Kubernetes does.
Do I have to use Docker Agent and Agentflow together?
No, they are separate projects solving the same problem in different ecosystems — Docker Agent as a YAML-plus-runtime tool, Agentflow as a Python framework. Nothing in the dossier ties them together beyond both following the same pluggable pattern.
What happens if I pick delegation when I actually needed parallel background tasks?
The run will still complete, but slower than necessary. Docker Agent's own documentation is explicit that the delegation tool blocks the coordinator until the child agent finishes, which is the wrong choice when several independent tasks could have run at the same time under the background_agents toolset instead.
Does packaging an agent as an OCI image make it fully portable?
Only the declarative config travels with the image — the model, tools and sub-agent structure. Secrets, live memory and any connected data sources still need to be set up separately wherever the image is pulled and run.
Is Agentflow the same as LangGraph?
Agentflow is described by its own project as LangGraph-inspired, and it borrows LangGraph's nodes-and-edges vocabulary, but it is a distinct framework with its own graph engine, command-line tooling and client — not a repackaging of LangGraph itself.
Glossary
- Orchestration — the logic that decides which AI model, tool or sub-agent runs next, and how their outputs combine.
- Pluggable — designed so a component (model, tool, memory backend, routing pattern) can be swapped without changing the rest of the system.
- MCP (Model Context Protocol) — a standard way for AI agents to connect to external tools or data sources, whether local, remote, or containerised.
- Sub-agent — a specialised agent that a coordinator agent can delegate a task to, expecting a result back.
- Delegation (sub_agents) — a hierarchical multi-agent pattern where a parent agent sends a task to a child and waits for it to finish before continuing.
- Handoff — a peer-to-peer multi-agent pattern where the active agent changes but the conversation and its history stay in one session.
- StateGraph — a description of an agent workflow as nodes (steps) and edges (transitions), compiled into a runnable graph.
- Checkpointing — saving the current state of a workflow so it can be paused, resumed or recovered after a failure.
- ToolNode — a built-in component that receives tool-call requests, runs the matching function, and returns the result to the graph.
- OCI registry — a standard storage and distribution system for container images, and, for Docker Agent, packaged AI agents.
- Human-in-the-loop — a pause point in an automated workflow where a person must approve or provide input before execution continues.
- YAML — a plain-text configuration format readable by both humans and programs.
- LLM-agnostic — not tied to one specific language model provider; able to work with several interchangeably.
Sources
- docker/cagent README — GitHub / Docker
- StateGraph and Nodes — AgentFlow concepts — 10xScale AgentFlow docs
- 10xHub/Agentflow — GitHub / 10xHub
- Docker Agent — Run AI agents from YAML, like containers — Docker
- Multi-Agent Systems – Docker Agent Docs — Docker
- Agents and Tools — AgentFlow concepts — 10xScale AgentFlow docs
- Workflows · Pull Request #2507 · docker/docker-agent — GitHub / Docker
- 10xHub/Agentflow (feature summary) — GitHub / 10xHub