Parts

When to split an agent

Keep one agent while its job is coherent, split only when several reasons line up, and pick the boundary that fits - a tool, a flow tool, a delegate, another plugin's part under uses:, or an A2A agent.

For: plugin authors.

Start with one agent for a coherent task. Splitting it adds definitions and evals to maintain, a contract between agents, more model calls and a context transfer that the original agent did not need.

Create a second agent when the benefits of that boundary justify those costs.

This page is about splitting an agent. Splitting a plugin, when its parts change at different speeds or belong to different people, is on How to structure plugins.

Keep one agent while the job is coherent

One agent with one set of instructions, tools and skills is the easiest to evaluate, judge and change. An agent that fails is usually fixed without a split: a skill for what some jobs need, a tool for what a program can work out, a hook for what must never happen (Where a fix belongs).

Split when several reasons line up

  • Its context no longer fits. The conversation grows past what the model handles well, even with compaction, and a part of the work needs only a slice of it.
  • It needs permissions the rest must not have. One part writes, sends or spends; the rest only reads. Split, and only that part's agent is granted the writes.
  • Its parts scale or fail apart. One part needs a GPU node or a sandbox, runs for hours, or fails often, and the rest should neither wait for it nor run again with it.
  • Another team reuses a part. The same steps serve another plugin's agents, which should call them rather than copy them.
  • Another team owns a part. It has its own releases, evals and rollouts, and its own people to ask.

One reason alone seldom pays for a boundary: a long context can be compacted, and a write can wait for a person. Two or more together usually do. Separation of duties is the exception: when one agent must not hold two duties together, such as proposing a payment and approving it, that alone settles the split.

A quarantine child is not a split. An agent that acts and must read outside text, such as mail or web pages, lists oz.quarantine: the same agent reads the text in a child job held to read-only tools and answers in a bounded shape, so the reading does not taint the agent that acts. It needs none of the reasons above, and keeps that text out of the acting agent's context.

Pick the boundary

BoundaryUse it forWhat it costsWhat survives a restartAn example
A toolA deterministic step with no judgementIts function's definition in every request of the agents granted itThe call's result, recorded in the job's history once it returns, so a replay does not call it again; a failed call runs again only when it is read-only or honours its idempotency key, and otherwise goes back to the model as an errornet-diag's probes, plugins/net-diag/src/oz0_net_diag/server.py
A flow toolA fixed sequence the agent decides to start but never reorders or skipsOne function's definition; a child job of steps when calledThe flow is a child job with its own history: steps that finished are not run again, and the agent waits for its outputNone of the plugins OZ ships exposes one yet; plugins/support-triage/flows/support-triage.yaml fixes the same kind of order from outside, with the agent as one step
A delegateA part that needs judgement of its own: its own instructions, tools, budget and grantoz.delegate's definition; a child job and its model calls when one runsThe child is a job of its own with its own history, and resumes where it was as any job does; the parent waits for its answer and holds no worker meanwhileexamples/openai-desk/agents/triage.yaml
uses:Another plugin's tool, agent or skill, at its owner's version and under its owner's controlA grant at install, and then what the part costs as a tool or a delegateWhat the part survives as a tool call or a child jobplugins/pr-reviewer/oz0-plugin.yaml uses github's read functions; plugins/support-triage/oz0-plugin.yaml uses the ticket systems' connectors and email
A2AAn agent outside the tenant or outside OZIts price per task (task_usd), charged to the job; no token budget reaches what it spends on its own sideThe task lives at the outside agent: a node that stops leaves it, and the next node follows the same taskplugins/a2a-foundry/agents/oz0-foundry.yaml, and plugins/a2a-remote for any A2A agent

Each boundary has its own page: tools, flows as tools, delegation, plugins that use other plugins and outside A2A agents. How agents combine lists every way they work together.

Deciding

Start with one agent, then choose a boundary that fits the work:

  • Make a part that needs no judgement a tool.
  • Make steps that must always run in the same order a flow, and give the agent the flow as a tool.
  • Make a part a delegate in the same plugin when it needs judgement but different instructions, tools, permissions or its own budget, and several reasons above line up.
  • Use another team's or plugin's existing work through uses: instead of copying it.
  • Reach an agent outside your tenant or outside OZ over A2A.

A split made too early

A delegate that needs most of its parent's context to do its part is a sign the split came too early: the parent hands over what it knows, the child reads it again, and the two pay for the same context twice. Merge the two back into one agent, or move the shared knowledge into a skill both can read.

The delegation_context finding names such a parent and child pair, measured from the jobs' history: over 14 days and at least 20 delegations, a median of more than 60% of the parent's context handed to the child. It only reports; each delegation's step shows the sizes it was measured from.

Measure a merge or a split

Before you keep a second agent, try the job with one: the second agent's role as a skill, its checks as an outcome check. Run both shapes on the same whole-job eval cases, about ten of them, with three runs each, in a comparison of a changed agent (oz0 compare start <agent> --variant draft=<folder> --nodes pool=dev --runs 3 --budget <dollars>). Judge by which cases flipped (oz0 compare show <id> --runs lists every run with its case), not by the pass rate alone: two shapes with the same rate can each fail cases the other passes.

Keep the split when the one-agent shape fails cases the split passes and passes none the split fails, or when separation of duties requires it.

The build kit asks the same questions before it scaffolds: its oz0-choose-the-kind skill places each part of a request (a role as a skill, a step with no judgement as a tool, a fixed order as a flow tool, a reviewer as an outcome check) and writes a delegate only for the reasons above (The build kit for coding agents).

Signs a split may not pay

Three findings read the delegations of each parent and child over 14 days, and each only reports: delegation_context, a child handed most of its parent's context; delegate_every_job, a child its parent delegates to in nearly every job; and delegate_chain, children the parent runs in a fixed order, each one's answer the next one's task. Before you merge on their word, measure it: a comparison that folds the child into the parent runs the parent with the child's instructions as a skill and the child's tools as its own, on the parent's eval cases, and lists the cases that flipped.

Keep the split where the folded agent does worse, and where a duty rule keeps the two apart.

Copyright © 2026