AgentCanvas / Pages / Developer Guide / Core / Decisions / Observability / ADR-observability-002
2026-04-02
Date
2026-04-02
Status
accepted
Field
observability
Old ID
ADR-016

Context

AgentCanvas had no mechanism to intercept graph execution for logging, validation, or policy enforcement. Researchers wanting to debug VLN agent behavior (log LLM outputs, block early stops, export metrics) had to modify node code or the framework itself. Claude Code's hook system (PreToolUse, PostToolUse, Stop) demonstrated that interceptors can be added as external shell commands without modifying the execution engine.

Decision

(1) Five hook events: PreNodeExecute, PostNodeExecute, GraphStart, GraphComplete, GraphError. (2) Shell subprocess hooks via asyncio.create_subprocess_exec with stdin/stdout JSON protocol. (3) HookDef dataclass stored in GraphDefinition.hooks — hooks travel with saved graphs. (4) HookRunner indexes by event at init, matches by exact type, "*" wildcard, or "prefix__*" prefix. (5) PreNodeExecute can block (skip node) or modify inputs. PostNodeExecute fires on both success and error paths (try/except wrapping forward()). (6) safe_serialize() converts numpy/PIL/bytes to metadata-only JSON — no full data through hook pipe. (7) Fail-open: timeout, crash, malformed JSON all default to continue. (8) Zero-cost when unused: single has_hooks() boolean check guards all hook logic.

Alternatives

(a) In-process Python callable hooks — rejected for V1 due to lack of isolation (hook bugs can corrupt executor state), serialization issues (callables not JSON-serializable), and security risk. Can be added as a second hook type later. (b) HTTP webhook hooks — deferred for V1, subprocess covers local use cases.

Rationale

Subprocess isolation outweighs the ~5-20ms latency per invocation. For a VLN agent with 14 nodes/iteration and 500 iterations, a wildcard hook adds ~140s overhead — significant but acceptable for debugging. The HookRunner abstraction supports adding in-process and HTTP hook types later without changing executor integration points. Hooks separate "what the agent does" (graph) from "what you observe about it" (hooks) — same separation-of-concerns as middleware in web frameworks.

Affected docs

capabilities/hook-system.md, blueprint.md, architecture.md, glossary.md