Manager Agents

A global script is the scratch form. It lives on your machine, you run it by path, and when it stops being useful you delete it.

When a workflow is worth keeping — worth publishing, deploying, or running on a schedule — it becomes an agent whose job is orchestrating other agents.

eslint-manager/
├── src/
│   ├── scripts/
│   │   ├── audit.ts        # boots a fleet, runs the audit
│   │   └── fix.ts          # boots a fleet, applies fixes
│   ├── prompts/            # its own prompts
│   └── boot.vue            # who this manager is
└── axon.config.ts
// src/scripts/audit.ts
const { linter, reviewer } = await Fleet({
    linter:   "@arclabs/linter",
    reviewer: "@arclabs/reviewer",
})

const findings = await linter.request("audit this repo against our ruleset")
const triage   = await reviewer.request(`which of these matter?\n\n${findings.text}`)

await axon.request(`summarise for the team:\n\n${triage.text}`)

There is no separate workflow artifact, and there does not need to be. An agent already has scripts, prompts, config, routes, hooks, a policy, and a place in the registry. A manager is an ordinary agent that happens to delegate.

What you get for free

This is the reason the pattern is worth knowing. Everything already built for agents applies unchanged:

How
Publishaxon publish — it's an agent
Installaxon install @cody/eslint-manager
Versionpinned like any registry package
Deployaxon deploy — routes, URL, API key
Schedulecron against a script or a route
TriggerHTTP routes, hooks, email, the TUI palette
Observeits own session trace, like any agent

A new artifact kind would inherit none of that and would have to grow all of it again.

The manager can think

A manager agent has an identity and a full agent loop of its own. That is not vestigial — it is what makes a manager more capable than a script.

A script routes work by whatever its author hardcoded. A manager can decide:

// src/scripts/handle.ts
const { issue } = defineArgs<{ issue: string }>()

const routing = await axon.request(
    `Which specialist should handle this? Answer with one name: security, perf, docs.\n\n${issue}`,
)

const { specialist } = await Fleet({
    specialist: `@arclabs/${routing.text.trim()}`,
})

const result = await specialist.request(issue)

The delegation target is chosen at runtime, by an agent, based on the work. That is the capability a plain script doesn't have — and the reason "an orchestrator is just an agent" is a feature rather than a compromise.

Managers that never call axon.request() are fine too. Delegation with no judgment is a legitimate manager; it just doesn't need the loop.

Triggering it

The same manager runs from everywhere an agent does:

axon run audit                    # headless, from the terminal
// server/api/audit.post.ts — as a service
export default defineEventHandler(async (event) => {
    const { stream } = axon.scripts.stream("audit")
    return sendStream(event, stream)
})
// server/plugins/nightly.ts — on a hook
export default defineAxonPlugin(async (axon) => {
    axon.hooks.hook("github:pull_request.opened", async ({ number }) => {
        void axon.scripts.request("audit", { pr: String(number) })
    })
})

Note the shape of that last one. The plugin subscribes to a hook its own agent's module emits, then delegates to a script that boots whatever fleet it needs. The manager never reaches into another agent's lifecycle — it handles its own events and talks to other agents through the protocol. See The Boundary.

Declaring what it needs

A published manager cannot use relative paths — the consumer has no ../linter. Refer to fleet members by registry name, pinned:

const { linter } = await Fleet({ linter: "@arclabs/linter@^1.2" })

The first run resolves and installs them; later runs read the cache. Pre-install with axon install if you would rather not pay for it at runtime. See Resolving Agents.

Script or manager?

Write a global script when the work is yours, local, and disposable. No folder, no config, no ceremony — a file you run.

Write a manager agent when the work needs to outlive the file: to be shared across repos, installed by a teammate, deployed as a service, or run on a schedule.

The graduation path is short. A *.axon.ts script that has earned its keep becomes axon init, and the script body moves into src/scripts/ mostly unchanged — the calls are identical, and the manager gains an ambient axon it can use or ignore.


Next: The Running Fleet — agents live on your machine.