Agent Editing Guide
This guide is the operational playbook for agents editing Noma documents. The rule is simple: discover IDs, patch the smallest stable block, validate the result, and never rewrite a whole file unless the user explicitly asks for a migration.
The safe editing loop
| Step | Command | Purpose |
|---|---|---|
| 1. Read | noma render file.noma --to llm --budget 12000 | Get deterministic context without HTML noise. |
| 2. Discover IDs | noma ids file.noma | Find canonical IDs and aliases before patching. |
| 3. Validate | noma check file.noma | Record the pre-edit diagnostic state. |
| 4. Patch | noma patch file.noma --ops ops.json --inplace | Apply a transaction of targeted operations. |
| 5. Re-check | noma check file.noma | Confirm the edit did not introduce errors. |
| 6. Render | noma render file.noma --to html --strict --out artifact.html | Produce a safe published artifact. |
Choose the smallest operation
| User intent | Preferred op |
|---|---|
| Replace an entire semantic block | replace_block |
| Change only the prose/body | replace_body |
| Rename a section title but keep links stable | update_heading |
| Insert evidence, a task, or a new card | add_block |
| Remove obsolete material | delete_block |
| Change confidence, status, owner, or source | update_attribute |
| Change a canonical ID and retarget references | rename_id |
Transaction shape
Patch files should use the transaction wrapper when an edit has more than one operation or when validation should guard the write.
{
"prevalidate": true,
"postvalidate": true,
"ops": [
{
"op": "update_attribute",
"id": "launch-decision",
"key": "status",
"value": "accepted"
}
]
}
Guardrails for agents
- Prefer
replace_bodyoverreplace_blockwhen attributes and children should survive. - Prefer
update_headingover text replacement for section titles. - Use
rename_idonly when the user accepts a breaking ID change. - Preserve aliases unless the user asks to remove them.
- Validate fragments before insertion.
- Use
--strictfor published/team artifacts. - Keep raw
::html,::svg, and::scriptout of agent-generated content unless explicitly requested.
Minimal agent prompt
You are editing a Noma document. First discover IDs with noma ids. Choose the smallest patch operation. Apply edits with noma patch --ops. Run noma check after the patch. Do not rewrite the whole file unless explicitly requested.
When to ask a human
Ask before editing when:
- The requested target has no stable ID.
- Multiple aliases could refer to different sections.
- A patch would delete evidence, citations, or accepted decisions.
- The edit requires raw HTML/script escape hatches.
- Validation fails after a patch and the fix is not mechanical.
MCP and SDK status
The MCP server exposes read_doc, list_ids, validate_doc, and patch_block over stdio. The Agent SDK wraps that server and remains experimental until the protocol annexes graduate. Treat the CLI and schemas as the stable contract; treat SDK ergonomics as subject to change during v0.x.
MCP host setup
Use the published stdio server from any MCP host that accepts command-based server definitions:
{
"mcpServers": {
"noma": {
"command": "npx",
"args": ["-y", "@ferax564/noma-mcp-server"]
}
}
}
The server should be pointed at absolute file paths by the caller. It does not invent edits: agents still need to discover IDs, choose a small patch operation, and validate after the patch.
SDK workflow
Use the SDK when an agent integration needs a typed client and retry-aware source patches:
import { NomaTools, NomaWorkflow } from "@ferax564/noma-agent-sdk";
const tools = await NomaTools.spawn();
try {
const ids = await tools.listIds("/repo/memo.noma");
console.log(ids.ids);
const workflow = new NomaWorkflow(tools);
const result = await workflow.safePatch("/repo/memo.noma", {
op: "replace_body",
id: "summary",
content: "Updated summary text.",
});
if (!result.ok) {
throw new Error(`${result.code}: ${result.error}`);
}
} finally {
await tools.close();
}
safePatch reads the current SHA before patching and retries only on sha_mismatch. Same-file patches inside one workflow are serialized so two local agent tasks do not race each other.