Improve

Where a fix belongs

When an agent fails a job, keep the failure as an eval case, put the fix in the cheapest part that fixes it, and run the eval again. Seven parts, cheapest first, each with an example from the plugins OZ ships.

For: Plugin authors correcting a failure.

Keep a failed job as an eval case before changing the agent. Then choose the least costly part that can correct the failure and rerun that case. Instructions sent on every model call have a recurring cost; a skill or tool may be needed only by some jobs.

The rule

  1. Keep the failure. Keep the job as an eval case of its agent (Keep a job as an eval case). The case replays offline, and it fails until the agent is fixed.
  2. Fix it in the cheapest part that fixes it. Go down the seven steps below and stop at the first one that holds the fix. Each step is preferred to every step after it.
  3. Run the eval again. The kept case passes and the agent's other cases still do. To see the changed agent beside the installed one on the same cases, run a comparison of a changed agent.

Always-on instructions are the last step, though they are where a fix is often written first: the agent sends them in full with every request. If you add some, cut some.

The seven steps

StepThe failures it fitsWhat it costsAn example OZ ships
1. A skillIt did not know something only some jobs need: a procedure, a domain's rules, how to read a formatOne line of the skills index in every request; its body only in the jobs that read itsupport-triage's skill: categories, urgency, teams, what a reply may promise
2. A script or a toolIt worked out what a program can compute, look up or checkEach function's definition in every request of an agent granted itpr-reviewer's run_tests; net-diag's probes
3. A tool's manualIt misused a connector's functions: the wrong order, the wrong arguments, a limit it did not knowOne index line for every agent granted the tool's functions; its body when readweb's web-research
4. DelegationThe job mixes two kinds of work, needs another plugin's agent, or its context grows past what one agent handles welloz.delegate's definition; a child job only when one runsopenai-desk's triage agent; the connectors' delegate agents
5. A hookIt must never do something, or must ask a person first, whatever its instructions sayNothing in the agent's requests; the hook runs at its eventssupport-triage's hold_promises; guardrails' redact, injection and command_guard
6. An outcome checkThe answer is wrong in a way a reader can check: missing, the wrong shape, unfaithful to its sources, inconsistentA judge's model call per round, on every jobpr-reviewer's outcome:
7. Always-on instructionsIt must hold on every requestEvery word, in every request, under no budgetThe longest prompts OZ ships

1. A skill

A skill fits knowledge that only some jobs need: a procedure, a domain's rules, how to read a format, a team's conventions. Each request carries one line for it, its name and description in the agent's skills index, and its body reaches the model only when the agent reads it.

The index counts against the agent's start-up budget, so a skill no job reads still costs its line, and may push another skill out of the budget. Write its description so the agent can tell when to read it.

  • plugins/support-triage/skills/support-triage/SKILL.md holds how the service desk triages a ticket: the categories, the urgency levels, choosing a team, and what a reply to the requester may and may not promise.
  • plugins/net-diag/skills/net-diag/SKILL.md holds the order to probe a network in: DNS, then TCP, then TLS and HTTP, stopping at the first answer that explains the symptom.

Terms a tenant's own people decide belong in memory instead (a skill or memory).

2. A script or a tool

A program fits whatever can be computed, looked up or checked: counting, parsing, dates, a lookup in a system, whether the tests pass. It answers the same way every time, and the model spends no tokens working it out. Write it as a function of a tool of your plugin (Tools).

A tool is not free: every request of an agent granted a function carries its definition, the name, the description and the input schema (what a definition costs). A tool earns its place by replacing steps the model would otherwise take. Grant an agent only the functions it calls.

  • pr-reviewer's run_tests (plugins/pr-reviewer/src/oz0_pr_reviewer/runner.py, declared in plugins/pr-reviewer/oz0-plugin.yaml) runs a pull request's tests in sandbox tier 1 and returns the runner's summary line, so the review says what the tests did instead of guessing it from the diff.
  • net-diag's dns_lookup, tcp_check and tls_check (plugins/net-diag/src/oz0_net_diag/server.py) answer what the network does from the node, which a model could only guess.

3. A tool's manual

A tool's manual fits an agent that misuses a connector's functions: it calls them in the wrong order, passes the wrong arguments, or does not know a limit. The functions' descriptions say what each one does; a manual is a skill of the connector that says how to use them together (A tool's manual).

Every agent granted any of the tool's functions gets it in its skills index, in its own plugin or any other, so the fix is made once, in the connector, for every agent that calls it. It costs one index line under the same start-up budget, and its body when read.

  • plugins/web/oz0-plugin.yaml names manual: [web-research] under its oz0_web tool.
  • The atlassian, atlassian-dc, gitlab and servicenow connectors name their own skills as their tools' manuals.

A manual is written by the connector's publisher. When the connector is another publisher's, send them a note with the failing case; meanwhile, a skill of your own plugin about how your agent uses those functions, a narrower grant, or a hook of your own is yours to change.

4. Delegation

Delegation fits a job that mixes two kinds of work, that needs another plugin's agent, or whose context grows past what one agent handles well. The child job has its own instructions, tools, budget and context, and the parent reads only its answer (Delegation). The parent's requests carry oz.delegate's definition; a child job and its model calls cost something only when one runs.

No plugin under plugins/ declares delegation: today. The shipped example is examples/openai-desk/agents/triage.yaml: its triage agent lists a writer and a billing agent under delegation.allow. The connectors' delegate agents, marked tags: [delegate], are what other plugins hand work to: plugins/servicenow/agents/servicenow.yaml, plugins/atlassian/agents/atlassian.yaml, plugins/web/agents/oz0-web-research.yaml and the A2A plugins' plugins/a2a-foundry/agents/oz0-foundry.yaml.

Not delegating is sometimes the fix. pr-reviewer reads a pull request with github's read functions and uses no agent of github (the comment above uses: in plugins/pr-reviewer/oz0-plugin.yaml): a delegate would add a child job and grant an agent that can approve, label and merge, for work that read functions do. When to split an agent says when a split pays.

5. A hook

A hook fits what the agent must never do, or must ask a person about first, whatever its instructions say. Instructions ask the model; a hook decides outside it, at its events: before or after a tool call, at a job's start or end (Hooks). It adds nothing to the agent's requests; it costs its own run at each event, and a model call when the hook asks a model.

  • plugins/support-triage/oz0-plugin.yaml declares hold_promises before every mail the flow sends: a reply that promises money, a refund or a date waits for a person. It may only escalate, so it never changes or refuses what the flow sends.
  • plugins/guardrails/oz0-plugin.yaml declares redact (personal data and secrets out of results and answers), injection (a result that reads like an injection goes to a person) and command_guard (a catastrophic shell command goes to a person).

When the decision rests only on which function is called and what it does, a rule of the tool policy, or your plugin's suggested policy, asks or refuses the call with no code at all; use a hook when the decision reads the call's content.

6. An outcome check

An outcome check fits an answer that is wrong in a way a reader can check: missing, in the wrong shape, unfaithful to its sources, inconsistent with itself. A judge, a second model outside the conversation, checks each answer before the job ends, and an answer that fails goes back to the agent with the judge's reasons (Outcome checks). It costs a judge's model call per round on every job, and another turn of the agent when an answer fails.

  • plugins/pr-reviewer/agents/oz0-pr-reviewer.yaml holds every review to plugins/pr-reviewer/rubrics/review.md under outcome:, with at most two rounds.
  • An outcome check that names no rubric is judged by the default deliverable rubric. When the deliverable is a file, or must agree with the files the job read, add files: read. Write a rubric of your own only for what the default cannot know.

7. Always-on instructions, last

An agent's instructions fit only what it needs on every request: its job, the order of its steps, what to do when unsure, what never to do. They are sent in full with every request, and no budget caps them: the start-up budget counts the skills index and plugins' start-up text, not the agent's own instructions.

If you add some, cut some. Every sentence you add to an agent's instructions takes one out, or moves one into a skill. Give the instructions' word count before and after in the change's description, so its reviewer sees what it costs.

The longest prompts of the plugins OZ ships:

PromptWords
plugins/setup-assistant/prompts/oz0-setup-assistant.md419 words
plugins/pr-reviewer/prompts/oz0-pr-reviewer.md298 words
plugins/support-triage/prompts/support-triage-agent.md294 words

One sentence of the first would sit better in a skill: "Write the condition in CEL over the call", with the list of names a condition may read. Only the jobs that turn a sentence into a tool rule need it, while most of the setup assistant's jobs explain the tenant; as a skill named the manual of its oz0_setup tool, it would cost one index line and reach every agent granted oz0_setup.cel_check.

From symptom to step

  • It did not know something that some jobs need: a skill.
  • It worked out what a program could: a script or a tool.
  • It misused a connector's function: the tool's manual.
  • It did two jobs at once: delegation.
  • It must never do something, or must ask first: a hook, or the tool policy.
  • The answer can be checked: an outcome check.
  • It must hold on every request: instructions, and cut something.

When the platform failed, not the agent

A job that waited for a node, ran out of a limit or failed at a model provider is no agent's fault. Step through it in the studio's debugger to see which step failed and why, and see Troubleshooting for nodes, plugins and servers.

An agent that follows the ladder for you

The Plugin improver is an agent that proposes reviewed, evidence-backed changes to your plugins: given a failing CI run, a finding or your request about one of your plugins, it works on a copy of the plugin's repository with the build kit's skills and a shell to run the plugin's own tests (in sandbox tier 1), goes down these seven steps, and ends with a changeset that a person approves before a draft pull request opens.

Its answer names the step it chose and, when it changed instructions, the word counts before and after.

Copyright © 2026