diagram
Document a routine start to end as a graph, storing each step as a linked object with its own notes so processes stay traceable and reviewable.
Instructions
Document what a routine does, start to end, as a graph. Stored as type='diagram'.
For a PROCESS, not a fact: note() records what is true, checkpoint() where the work stands, this one how a routine runs. Every step is a separate object that can carry its own explanation and its own links to other memories, which is what makes a diagram the source of truth for its domain instead of one more wall of prose.
Keep every label objective -- what happens at that step, nothing
more. The reasoning, caveats and history belong in that node's
note, where they explain without cluttering the flow.
review_after and source_ref matter most for a flow: it describes code, and the code moves.
Returns {"uid": ...}, or {"ok": False, "errors": [...]} with nothing written at all. Node positions are computed and stored server-side, so the flow renders identically for every reader -- see get_diagram().
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| also | No | other domain paths this flow belongs to, comma-separated. `domain` is the routine's own place in the tree; `also` is for the flows that run ACROSS routines -- several of them can be steps of one end-to-end process without any of them being the parent of the others. Cross-list each into that process's path and asking about it returns all of them, instead of hoping one search phrasing reaches every one. | |
| kind | No | 'flowchart', the only kind. | flowchart |
| tags | No | comma-separated keywords and synonyms. Retrieval is BM25 over content, tags and domain paths, and tags weigh second only to the body, so they make a memory findable by words its own text never uses: the identifier, the error string, the plain phrasing someone will type. A memory with none is reachable only by quoting itself. At most 1000 characters. | |
| edges | Yes | the wires between steps, as [{"from": "load", "to": "check", "label": "optional branch"}]. | |
| nodes | Yes | the steps, as [{"key": "load", "label": "Read the export window", "shape": "step", "note": "optional long explanation"}]. key is a stable id the edges refer to (letters, digits, '_' or '-'); shape is start|step|decision|io|end. Exactly one 'start' is required and every node must be reachable from it. Cycles are allowed -- a retry loop is a real flow, not a mistake. | |
| title | Yes | one line naming what this memory is about, in the words someone would look for it by. A list shows it instead of the opening of the body, and it outweighs every other field in search, so a title that repeats the type ("note about the parser") names nothing. At most 120 characters; a name that needs more is summarizing the body. | |
| domain | No | the subject this belongs to, as a path from the outermost scope in ('acme/x100/p200'). File it as deep as the fact is specific -- a note about one routine goes on the routine, and still comes back when someone asks about the module or the product above it. At most 200 characters. | |
| session | No | groups what one conversation writes. Leave it empty to use this server process's own stamp. | |
| summary | No | a few sentences on what the routine is for, indexed with the flow. | |
| source_ref | No | what the fact came FROM -- a path, a URL, a table name -- so a later pass can check the claim against the thing itself instead of inferring what to check from the wording. At most 500 characters. | |
| review_after | No | when this stops being safe to trust unchecked, as a date ('2026-11-01') or a span from today ('90d'). pulse() counts what is overdue in a scope as `scope.stale` and optimize_scan lists it. Leave it empty for anything that does not go stale -- most facts do not, and a date nobody meant is worse than none. |