magus v0.4.3 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
8 min read

Any other host

The four documented hosts are examples, not a fixed list. magus owns the guard rules and the verdict, not integration code per host, so the host-specific part is a template or a few lines of config you control, and adding a host is your edit rather than a new magus release.

That is a standing decision rather than a gap waiting to be filled. A codec per host would cost us upkeep as the products change, and it would cost you more than it costs us: wiring you did not write is wiring you cannot repair on the afternoon your host changes its event shape, and this guard fails OPEN, so a hook that quietly stopped judging looks exactly like a session with nothing to deny. Read the template once and it is yours.

Any host that can run a command and read its output fits.

what where
skills whichever directory your host discovers SKILL.md in
always-on rules AGENTS.md, if your host reads one
guard wiring whatever pre-tool hook or plugin your host offers
rehydration whatever session-start or post-compaction event fires
MCP MCP

Skills

Not every host reads the Agent Skills format. If yours discovers SKILL.md directories, install into the one it names:

magus agent install --tar | tar -xf - -C <the directory your host reads>

If it reads only an instruction file, run magus agent install for the AGENTS.md block it prints and paste that instead. Skills covers both.

MCP

Any client that takes the documented connection details and a bearer token can connect; see MCP. This wiring belongs to the host owner. An agent uses the CLI fallback when MCP is unavailable; it does not manually start Magus solely to obtain tools.

Guard hook

The wiring is the same shape everywhere: get the command or path out of the host event, hand it to magus session hook, and render the verdict into the host's reply.

printf '%s' "$command" | magus session hook -o 'template=<your host reply>'

If your host writes its payload as JSON with tool_input.command or tool_input.file_path, pipe the payload in unchanged: magus reads the envelope itself, infers a write from a file path, and picks up session_id and hook_event_name for attribution. Otherwise select the field yourself - jq -r '.<path>' is what the shipped templates use - and pass --path when the input is a file. A lease id is not a field you select out of the event: the guard inherits it from the worker's environment, which the orchestrator that spawned the worker has to export - see wiring a lease into a worker.

The fastest start is to copy magus-command.sh and set its override variables: HOST_EVENT_PATH, HOST_RESPONSE, and the two unavailable-response variables. Name your host on the command itself, sh magus-command.sh --agent-name <your host>: the template reads the host from that argument and nowhere else, and refuses a call without it (MGS3024) rather than answering in another host's dialect. That gets you the missing-binary and broken-binary handling without writing it again.

Three decisions are yours to make:

  • Which channel carries a deny. Most hosts have one that reaches the model.
  • Which channel carries an advise, and when it arrives. It is often not the gating event: a host that sends a message only with a denial has nothing to attach an advisory to, and its post-tool event is the channel instead, which lands after the call rather than before it. HOST_ADVISE_BRANCH reshapes the arm for whatever your host takes. Reserve __MAGUS_NO_ADVISE for a host that does worse than ignore a reply it does not know: one that treats an unsupported key as an error and then fails OPEN is disarmed by an advisory rather than merely deaf to it. Suppressed, an advise renders nothing at all. None of the four documented hosts needs it today.
  • What happens when magus cannot be found or cannot judge. Failing open keeps the session usable and is what every shipped template does. Say so visibly rather than exiting quietly, because an unguarded session you know about beats one you do not.

If you contribute the result back, add a magus-guard-coverage: line declaring what your glue carries per surface and decision. A parity gate reads those lines and fails the build when a host was never asked about a decision the contract grew.

Lease capture

Separate from the guard, and the same shape: pipe the host's pre-tool event to magus session hook when the tool being called is the one that hands work to a sub-agent.

printf '%s' "$event" | magus session hook --agent-name <your host> >/dev/null 2>&1; exit 0

magus recognizes a lease by the FIELD it carries, never by a tool name it would have to enumerate per host: a tool_input with a prompt is a spawn. It reads the prompt as the handed context, takes the callee's label from subagent_type, then description, then tool_name, and takes the parent's session from session_id. If your host names those fields differently, reshape the payload before piping it - jq is enough.

The ordering is deliberate: a payload carrying command or file_path is judged as a command or a write exactly as before, and only one carrying neither is read as a spawn. Adding this wiring cannot change a verdict you already had.

Nothing judges a lease. A prompt is prose, not a command line, so the verdict is always a pass and a prompt that mentions a denied command is recorded rather than blocked. Discard the output and exit 0.

The event

One agent_spawn event per lease, in the same activity trail and the same listing as every other kind - no new endpoint, and the console's activity filters already select it.

field what it carries
time when the handoff was observed
host, session the PARENT: the host you named, and its own session id
actor agent
action the child's label, or agent.spawn when the payload named none
lease the job the context declared, when it declared one (see below)
request_ref the handed context, fetched with GetPayload
request_bytes how much context was handed over
outcome ok means the handoff was OBSERVED, never that the child succeeded

The context is a blob, not a field. A lease prompt runs to kilobytes and can carry anything the orchestrator pasted into it, so the event line holds a reference and the body is fetched deliberately, one row at a time. It is redacted through the same resolver as every other trail write, but it is still durable prose on disk: treat the activity trail as readable by anyone who can read the workspace cache.

Correlating a spawn to a lease

Correlation is COOPERATIVE. No host event names a magus lease and magus will not guess one from prose, so an orchestrator that wants the join writes ONE marker:

lease: <id>

It must be the FIRST non-blank line of the handed context, and its trimmed text must be exactly that. The id is a bare token of letters, digits and the separators - _ . / :, at most 128 characters, with nothing after it on the line. Leading blank lines are skipped; the head of the context is capped at 4096 bytes, so a marker cannot hide behind a pathological first line.

Leading the prompt is the contract, not a convention. A delegation prompt routinely quotes a job listing, a file, or another agent's transcript, and a lease: line lifted from any of them would stamp the event with a lease this handoff has nothing to do with. Position is what separates a marker you wrote from one you pasted.

Anything else leaves lease empty: no marker, an id with prose after it, an id carrying other punctuation, a marker below the first line. That is a missing join, not an error, and it is the designed outcome for an orchestrator that never opted in.

Notifications

Wire any event that means a human is needed to magus session notify; see Attention hooks.

Recording where the work stands

Wire whatever event fires when a session ends to magus-checkpoint.sh, passing your host's name as --agent-name <your host>. magus session lists what it records.

The requirements are close to nothing, which is deliberate. magus reads the revision, branch and dirtiness from the tree itself, so a host that emits no payload at all still produces a usable checkpoint. If your host does carry a session id and a transcript path, pipe its event in and magus takes them from the envelope, or pass --session and --transcript. Both are pointers magus records and never opens.

magus needs no release to learn about your host. --agent-name is an opaque label you choose, exactly as on the guard hook.

Handing a session its state back

If your host has an event for "a session started" or "the history was compacted", wire it to magus-rehydrate.sh and whatever it prints reaches the model as context. It runs magus session --brief, which reads this checkout off the disk: branch and revision, commits not yet on the base ref, the dirty tree classified, the live leases, the last recorded run's failures, the guard wiring, and where the rules live. Set REHYDRATE_RULES to your host's own instruction file.

Nothing about it is host-shaped except which event you hang it on. If your host has no such event, run magus session --brief by hand and paste it, or read it yourself: it is the same answer either way.

Coverage and limits

Whatever your host's hook surface can carry. One binary produces the rules, so they are identical everywhere, and what differs is only how much of a verdict survives the trip to the model. Parity across hosts records that for the documented four.

Verify

printf '%s' 'git stash' | magus session hook -o name
magus doctor

The first proves magus judges at all from your shell. guard wiring in doctor loads the harness descriptors available to this workspace and reports each one as verified, uncovered, or invalid. A host without a descriptor is portable by design, but its copied adapter is not automatically verifiable.

agentsguardhooksintegrationtemplate
Last updated (a9ff8609)
Earlier changes on this page (7)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. See workspace.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). See operations.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

Sandbox

The restricted filesystem and environment a target runs in, so builds stay reproducible and side-effect-free. See sandbox.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Session

An agent host's conversation, by the id the host delivers to its hooks. magus never mints one: a record with no session is unattributed, and the OS user it carries says whose account ran it.

Job

The unit of delegated work, and one row of the job store: what an orchestrating agent handed out, with its goal, the checkpoint it was cut against, the paths it may write or must not touch, and the one check it runs. A job's holder is either a session, for work an orchestrator handed out, or the server, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. See doctrine.

A job is not a run. magus run build web is a run, and no job exists for it. A job causes runs: its check executes as one, and a server job records the invocation of its last one. Jobs are listed with magus ls jobs and in the console's Jobs view; runs are listed in the Runs view.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate.

Lease

The grant a holder takes on a job: the write and read paths that job declared, enforced in the checkout that took it with magus job exec. A job is the piece of work; a lease is permission over it.

Lease id

The short identifier a worker carries (the --lease flag, or the magus.lease member of the W3C BAGGAGE environment channel) so its runs, journal facts, and guard verdicts attribute to the job it holds. Letters, digits and -_./: only.

Advisor

One read-only check from the advice suite: it reads the changeset through magus and writes one titled section of findings. The same advisors run as a pull request comment in CI and inside magus diff --impact locally.

Conventions

Placeholders

Angle brackets mark a value you replace with your own - never type the brackets:

magus run <target>
magus completion <shell>    # e.g. bash, zsh, fish

<target>, <path>, <shell>, <name> and the like are stand-ins, not literal text.