Skip to main content

Nodes

Every graph node, filterable by category or capability. Each card is a technical datasheet: what it consumes, what it produces, which policies apply, and which file owns the implementation.

Five categories map to distinct responsibilities:

  • Safety — cannot be bypassed by mode, modality, or tone
  • Memory — retrieval and structured working context
  • Routing — dispatch to the right response pathway
  • Extraction — post-response LLM side effects that run in parallel
  • Terminal — transcript finalization, pure state manipulation
8nodes
5LLM
6retry=2
3reducers
2parallel
showing 8 of 8
01SafetyCannot be bypassed by mode or modality.

crisis_gate_node

LLMretry=2

Hard safety boundary. Runs BEFORE memory retrieval. Four-layer classification: (1) deterministic override, (2) regex ladder, (3) optional LLM fallback, (4) policy normalization. Returns Command(goto=...) that routes the turn.

inputsstate.messagestate.history[-6:]
outputsstate.crisisstate.routing.routestate.diagnostics
agent/nodes/crisis_gate.py::run_crisis_gate_node
02SafetyCannot be bypassed by mode or modality.

crisis_response_node

LLMretry=2

Generates crisis response with PFA overlay. Only runs on the crisis branch. Uses a tighter prompt with safety resource surfacing and a single clarifying question.

inputsstate.crisisstate.history
outputsstate.response
agent/nodes/crisis_response.py::run_crisis_response_node
03SafetyCannot be bypassed by mode or modality.

crisis_log_node

retry=2

Always-on audit log. Appends a CrisisLogRecord regardless of memory mode — the privacy asymmetry is deliberate per schema.yaml §2. Never skipped, never rate-limited.

inputsstate.crisisstate.routingstate.message
outputscrisis_log backend (side effect)
agent/nodes/crisis_log.py::run_crisis_log_node
04MemoryRetrieval and structured working context.

load_memory_node

retry=2

Therapeutic branch only. Retrieves semantic + episodic + procedural context via hybrid RRF retrieval. Returns structured WorkingMemoryEntry dicts — formatting happens on demand at prompt-build time.

inputsstate.messagestate.session_idstate.user_id
outputsstate.working_memorystate.memorystate.diagnostics
skip when
crisis branch skips retrievalincognito mode returns empty
agent/nodes/load_memory.py::run_load_memory_node
05RoutingDispatches to the right response pathway.

therapeutic_subgraph

LLMsubgraph

Compiled subgraph with dispatcher + 6 mode nodes. Uses TherapeuticSubgraphOutput to restrict what flows back to the parent, preventing reducer double-counting on transcript/history. Each child node has its own RetryPolicy.

inputsstate.messagestate.working_memorystate.progress
outputsstate.routingstate.responsestate.progress
agent/therapeutic/graph.py::build_therapeutic_subgraph
06TerminalTranscript finalization. Pure state, no I/O.

finalize_turn_node

operator.add

Appends the assistant reply as a single-element delta. The operator.add reducer on transcript/history handles accumulation. Returns empty delta for blank/whitespace responses to keep the transcript clean. No I/O, so no retry.

inputsstate.response.textstate.routing.mode
outputsstate.transcript [+1]state.history [+1]
agent/nodes/finalize_turn.py::run_finalize_turn_node
07ExtractionPost-response LLM side effects. Parallel fan-out.

extract_semantic_facts_node

LLMretry=2_merge_dictsparallel

LLM structured-output call that extracts semantic candidates, then runs deterministic write policy. Low-risk facts may commit immediately; sensitive or interpretive candidates can be held for session end or repetition. Runs in parallel with extract_procedural_rules_node.

inputsstate.messagestate.response.text
outputsmemory_store / session buffer (side effect)state.diagnostics
skip when
crisis pathno llm_clientincognito modesmall-talk gate triggered
agent/nodes/extract_facts.py::run_extract_semantic_facts_node
08ExtractionPost-response LLM side effects. Parallel fan-out.

extract_procedural_rules_node

LLMretry=2_merge_dictsparallel

LLM structured-output call that extracts procedural candidates, then runs deterministic write policy. Explicit durable instructions may commit immediately; implicit preferences can be held for session-end promotion. Same parallel lane as extract_semantic_facts_node.

inputsstate.messagestate.response.text
outputsprocedural profile / session buffer (side effect)state.diagnostics
skip when
crisis pathno llm_clientincognito modesmall-talk gate triggered
agent/nodes/extract_procedural_rules.py::run_extract_procedural_rules_node

Adding a new node

When you add a node to the graph, think through three things:

Does it do I/O? If yes, register it with retry_policy=RetryPolicy(max_attempts=2) in build_agent_workflow. The retry policy is defense-in-depth for transient failures that escape the node's own error handling.

Does it write to a shared state field? If multiple nodes write to the same field (like diagnostics or progress), the field needs a reducer (_merge_dicts for dicts, operator.add for lists) in AgentState. Without a reducer, nodes will clobber each other's writes.

Can it run in parallel? If the node has no ordering dependency with its siblings (the way the two extractors don't), wire it as a fan-out edge from its parent. The reducers handle concurrent writes safely.