# Tool Execution Pipeline
This graph shows where policy, hooks, sandboxing, filesystem guards, result rewriting, final-outcome observation, and UI rendering fit without changing the loop. The transformable extension points are the `tools/pre-execute`, `tools/execute`, and `tools/post-execute` waterfalls; monotonic guards and `tools/result` are the owner-enforced boundaries around them.
```mermaid
flowchart TD
model["Assistant message contains tool-call block"]
toolCall["Session event: tool/call
logged before execution"]
presentCall["UI pending card
presentCall(args)"]
pre["tools/pre-execute waterfall
hooks, permission, sandbox"]
guards["Registered monotonic guards
deny or abstain; identity protected"]
denied["denied or approval refused
tool body skipped"]
approval["ctx.approval one-shot prompt
absent or unanswerable: deny"]
around["tools/execute waterfall
timeout, retry, metrics (around dispatch)"]
toolBody["Registered tool execute() body"]
fsGate["fs/write-intent or fs/edit-intent
tool-fs mutations only"]
owned["Tool-owned session events
todo/write, fs/observed, hook/invoked, hook/result, tool/code-dispatch"]
post["tools/post-execute waterfall
accept, block, replace, add context"]
final["tools/result synchronous notification
frozen authoritative outcome"]
context["Active-batch additionalContexts FIFO
context/message after recorded tool results"]
toolResult["Session event: tool/result
single model-facing outcome"]
allResults["Tool batch settled
recorded tool/result events complete"]
presentResult["UI completed card
presentResult(args, result)"]
model --> toolCall
toolCall --> presentCall
toolCall --> pre
pre -->|allow| guards
guards -->|allow| around
guards -->|deny| denied
around --> toolBody
pre -->|deny| denied
pre -->|ask| approval
approval -->|allowed-once| guards
approval -->|rejected, cancelled, unavailable| denied
denied --> post
toolBody --> fsGate
fsGate --> toolBody
toolBody --> owned
toolBody --> around
around --> post
post --> final
final --> toolResult
toolResult --> presentResult
toolResult --> allResults
allResults --> context
```
Filesystem read-before-edit checks stay below `tool-fs` on `fs/*` events. Generic pre/post waterfalls host hooks and approval policy; `ctx.approval` resolves asks before monotonic guards, and owner policy that must not be reordered remains a registered guard. Around-dispatch concerns such as timeouts wrap `tools/execute`, while `tools/result` observes the immutable outcome after transforms, lossless-JSON validation, and outer error normalization. This lets hooks span tool families without coupling the tools to one policy service. Code Mode sends both the reserved `run_code` transport and its serialized sub-calls through the pipeline; sub-calls carry the parent token, log `tool/code-dispatch`, surface denials as binding rejections, and omit `additionalContexts` to preserve call/result adjacency.
Maintenance mode: curated Mermaid flow; exact tool schemas and event signatures live in generated catalogs.