A procedure it follows
Ask a model the same question twice and it will take two different routes to the answer. Where there is a right way to do something — a research procedure, an incident runbook, a compliance check — that variability is the problem.
A procedure is that method, written down, which the agent navigates instead of inventing one.
Procedure and mission are the same thing. These pages say procedure; the CLI flags and log lines say mission (
--mission,runs ONE mission (sealed)).
A mission has two lives, and both matter:
| in the workspace | a build session. You describe what you want, it takes shape beside the conversation, and what you settle on is saved as the cards below |
| sealed onto a runner | a fixed procedure. An outside caller asks a question and gets that method every time, and cannot ask for a different one |
The first is how you make one; the second is how you ship it. This page is what sits in between — the cards themselves, which are worth being able to read even though you did not type them.
What it is made of
Section titled “What it is made of”Three things, and the agent reads all three:
| part | file | what it does |
|---|---|---|
| the map | _flowchart.md | which card handles which kind of question |
| the cards | one .md each | the actual steps for one kind of question |
| the fence | _manifest.md | what this procedure may touch, and nothing else |
My_Workflow/ sources/ _flowchart.md the map _manifest.md the fence find-case-law.md a card lookup-statute-text.md a card chunks.jsonl searchable index, built from the above vectors.binThe agent searches a procedure the way it searches anything else: it finds the map, locates the question on it, walks to the right card, and executes that card’s steps in order.
1 · The map
Section titled “1 · The map”Three node shapes carry meaning:
| shape | means |
|---|---|
[(name)] | search or read a collection of documents |
[[method: x]] | apply a rule defined in the card |
{question} | a decision the model makes |
2 · A card, field by field
Section titled “2 · A card, field by field”## card: find-case-lawid: find-case-lawintent: "Find decided cases on a point of law"match_cues: ["find a case", "is there authority", "what did the court hold"]domain: legalresources: memories: ["judgments", "judgment-full-text"]methods: - id: terminology-variations kind: rule apply: "The question may use everyday words where the source uses terms of art. Search several phrasings before concluding nothing exists."steps: - n: 1 do: "Search the judgments collection for the proposition" via: "memory: judgments" extract: "<hits> - candidate cases with their ids" then: "step 2" - n: 2 do: "Read the full text of the most relevant case" via: "memory: judgment-full-text" query: "<case_id>" extract: "<holding> - what the court actually held" then: "step 3" - n: 3 do: "Confirm the holding answers the question as asked" via: "ai: verify relevance" then: "branch: found -> return, more candidates -> step 2, none -> ask user"dos: - "Cite the case id with every proposition" - "Read the full text before relying on a summary"donts: hard: - "do NOT query the full-text collection with a question - it takes ids only" soft: - "do not stop at the first plausible case"done_check: "A holding, with its case id, that answers the question as asked"| field | what it is for |
|---|---|
id | how the map refers to this card |
intent | one line: what this card is for. The model matches on this |
match_cues | phrasings that should land here. Write how people actually ask |
resources.memories | which collections this card may use — must also be in the fence |
methods | named rules the steps refer to, so a rule is written once and reused |
steps | the procedure. do = what, via = with which resource, query = what to send it, then = where next |
dos / donts | hard is never to be done; soft is a strong preference |
done_check | how the agent knows it is finished — not “did it try” but “does it have the answer” |
via:names the resource;query:says what to send it. A step that names a collection without saying what to pass has been observed to make the model invent a call that does not exist, get an error, and answer from partial results instead.
3 · The fence
Section titled “3 · The fence”## memories judgments judgment-full-text case-summaries
## commands (none)The runner may use only what is listed here. Not “should” — may. Combined with
exec-policy enforce ON, NO cmdset, a procedure that lists no commands cannot run a shell at all.
This is what makes a procedure safe to expose to callers you do not control: they choose the question, never the method, and the method cannot reach outside its fence.
Writing one
Section titled “Writing one”You do not hand-author these files.
In the workspace, start a new session on a mission engine rather than chat. Then
describe what you want in conversation — what question arrives, what should be searched, what
must never happen. It takes shape in the panel beside the conversation as you talk, you correct it
in the same conversation, and each revision is saved and re-indexed as you go.
The YAML above is what it produces. You need to be able to read it — to check a step goes where you meant — but you do not need to write it.
That matters because the person who knows the procedure is rarely the person who wants to write YAML.
Never put an answer in a card
Section titled “Never put an answer in a card”Cards accept an examples: block, and it is tempting to paste in a worked example with its answer.
Measured. A card carried one example: a question, its answer, and the source id. Asked that exact question, the agent found the card, read the answer straight out of it, and returned in three steps without searching anything. It looked like excellent retrieval. It was recitation.
With the example removed, the same question took thirty-nine steps, searched honestly, and got it wrong — which had been the true state all along.
Examples teach shape. One that carries a real answer stops you measuring the system and starts you measuring the card.
Moving it to another machine
Section titled “Moving it to another machine”hexaeight-activate agskill-export --mission My_Workflow --out mission-My_Workflow.ziphexaeight-activate agskill-import --in mission-My_Workflow.zip --root ~/.hexaeight-harnessThe bundle carries the cards, the map and the fence. It does not carry the document collections they search — those must already exist on the target — and permissions never travel, because they are specific to an identity.
Import refuses to overwrite:
mission memory exists (use --force to overwrite). Without--forcenothing happened and the previous version is still the one running.
Check what a bundle holds before trusting it:
unzip -l mission-My_Workflow.zipThe card count is the number of .md files under sources/ minus _flowchart.md and
_manifest.md, which are not cards.
Locking an agent to one procedure
Section titled “Locking an agent to one procedure”An agent can be sealed so it runs exactly one procedure, and a caller cannot choose another:
hexaeight-activate engine --add runmission --name my-engine \ --mission My_Workflow \ --model "<route|model>" --router "<agent|url>" \ --dir <agent-dir> --file <wrapper>--file names a small wrapper script that sits in front of the engine. You do not write it:
add-external-agent creates it when it provisions a runner, in a folder beside the runner’s own.
Its job is to impose this door’s procedure on every turn and strip anything a caller sends that
tries to choose a different one.
It must live outside the agent’s folder, because each turn runs with that folder masked — a script kept inside it does not exist as far as the engine is concerned.
Proof at startup:
[hexaeight-agent] engine 'my-engine' runs ONE mission (sealed): My_WorkflowIf that line is absent the procedure is not sealed, and the agent will run whatever a caller asks for. See Other software calling it.
When a procedure misbehaves
Section titled “When a procedure misbehaves”| symptom | cause |
|---|---|
| it answers without searching | an examples: block contains the answer |
| it invents a call and fails | a step names a resource but no query |
| it cannot reach a collection | missing from the fence, or from resources.memories |
| an edit has no effect | the index was refreshed rather than rebuilt — see Troubleshooting |
| a caller ran a different procedure | the engine was re-sealed without --file, unbinding the wrapper |