06. Tool Runtime And Permission Skeleton
This chapter explains why tool execution cannot stay a plain function call. Real agent tools need a runtime boundary for preparation, execution, errors, events, and permission policy.
After reading this chapter, you should understand:
- the difference between tool definitions and tool execution runtime
- why a permission skeleton appears before dangerous tools
- why tool facts are separate from policy decisions
- how runtime events support both frontend debug and future telemetry
Background
Once the model can request tools, a dangerous temptation appears: call the tool directly from the agent loop.
That would make the loop own too much:
- registry lookup
- permission checks
- event emission
- error conversion
- tool execution
- output shaping
The project moved tool execution behind a runtime boundary before adding more tools.
Tool Runtime Boundary
The key file is:
lib/agent-tool-runtime.tsIt owns the lifecycle of a single tool call:
lookup tool
create permission request
decide permission
emit lifecycle events
execute handler
convert result
return AgentToolExecutionPermission Skeleton
The permission layer lives in:
lib/agent-permissions.tsIt models:
- tool annotations
- approval policy
- sandbox mode
- permission requests
- permission decisions
Current decisions are intentionally small:
- safe read-only built-ins can run
- path-denied tool calls fail before execution and become model-visible tool errors
- approval-required paths fail closed
- interactive approval resume is deferred
The permission request now carries both static tool facts and per-call data:
declaredPathAccess
effective pathAccess for the current sandboxMode
requestedPath from the tool argumentsThat means sandboxMode=danger_full_access can widen read-only file tools to absolute paths, while the default read_only mode keeps them inside the current project.
Why Tool Facts Are Separate From Policy
A tool declares facts:
readOnly: true
destructive: false
openWorld: false
idempotent: trueThe runtime applies policy to those facts. The tool does not decide whether it is allowed to run.
This matters because future user settings, project trust, sandbox mode, and approval hooks should all affect decisions without changing tool handlers.
Runtime Events
The tool runtime emits:
tool_permission_decided
approval_requested
tool_started
tool_finishedThese events later became visible in the Debug Console.
Git Evidence
Relevant commits:
567da1f Add agent tool runtime boundary
cdd881c Add agent permission policy skeletonDeferred Work
This phase did not implement:
- OS sandboxing
- approval resume
- user decision UI
- shell permission prompts
- write/edit confirmations
That restraint was intentional. The permission contract appeared before the risky tools.
Common Misunderstandings
Misunderstanding 1: Read-Only Tools Do Not Need A Runtime
Even read-only tools need argument validation, path policy, output truncation, error formatting, and events. Runtime boundaries are not only for risky tools.
Misunderstanding 2: Permission Policy Belongs Inside Each Tool
Tools should report facts: what path they access, whether they write, whether they need network. Whether execution is allowed belongs to policy.
The read-only tools still perform a realpath guard inside the handler. That is not a replacement for permission policy; it is a second safety check that catches symlink escapes after the pre-execution decision.
Misunderstanding 3: Shell Should Come First Because It Is Faster
Shell is powerful, but it has the largest safety surface. A runtime and permission skeleton keeps future shell behavior from becoming special-case code.
Chapter Summary
This chapter upgrades tool execution into a runtime contract. Tools describe capability, the runtime orchestrates execution, and the permission skeleton leaves room for sandbox and approval behavior.
Chapter Checkpoint
Verify that the key invariants of the tool contract and permission skeleton are locked down by tests (no key required):
npx tsx --test tests/agent-tool-contracts.test.tsMeasured: all 6 cases pass:
✔ tool groups expose current builtin surface
✔ current tool definitions declare runtime metadata explicitly
✔ provider-visible tools do not include runtime metadata
✔ provider-visible editing tools depend on run sandbox mode
✔ path access policies enforce current project and allowed roots
✔ relative path resolution follows the active path policy base
ℹ pass 6provider-visible tools do not include runtime metadata maps directly onto this chapter's "tool facts versus policy" boundary; the two path policy cases cover the rule that sandboxMode decides the effective pathAccess.