Skip to content

Sessions & path-aware policy

Most governance tools evaluate each call in isolation. TapPass also evaluates the path: the ordered history of what this agent has already done in this session. The same action can be allowed at minute one and blocked at minute ten, because of what came before it.

Every governed call, including blocked attempts, is appended to the session’s path after the decision. The tracker keeps, per session:

  • the ordered event list (behavior type, resource, timestamp), and
  • aggregates: count_by_type, unique_resources, total_events, first/last timestamps.

A session is identified by session_id; when the caller doesn’t supply one, the server pins one per (org, agent).

Three projections land in the policy input:

{
"state": {
"session": { "event_count": 17, "unique_resources": 4 },
"path": { "tools": ["read_file", "query_db", "read_file"],
"last": { "type": "TOOL_CALL", "resource": "read_file" } }
},
"path": { // opt-in: full projection
"session_id": "ses_…",
"events": [ /* capped at a fixed window */ ],
"aggregates": { /* counts, uniques, timestamps */ }
}
}
  • state.session, always available.
  • state.path.tools, the ordered prior tool trajectory; read by sequence and rate rules.
  • state.path.last, the immediate predecessor event (type + resource), regardless of type. Freshness rules key on it: “the gate must be the step directly before this one,” not “a gate exists somewhere in history.”
  • path, the full event projection, available when opt-in path projection is enabled for your org. Rules that read it (e.g. the rate_limit_tool_per_session template) require it.

If the path store is unavailable, state.session becomes {"unavailable": true} and path facts are absent, policy can treat “history unknown” as a reason to refuse, keeping the system fail-closed.

Concrete rules you can express today with built-in kinds:

Intent Rule kind Reads
No more than N calls to tool T per minute PerToolRateLimit state.tool_rate
Cap session spend at $X MaxSpend state.spend
Cap tokens per day MaxTokensPerDay state.tokens_used_today
Forbid tool B after tool A ran BlockToolSequence state.path.tools
Max calls per session overall SessionRateLimit state.session
Flag anomalous tool args vs learned baseline ToolArgOutlier findings.tool_baseline

BlockToolSequence is the taint primitive: “once read_secrets appears in the trajectory, block http_post for the rest of the session.” Taint is permanent within the session because the trajectory only grows.

Single-call rules can’t express the attacks and failures that actually hurt agents:

  • Data-leak chains, read a secret file, then exfiltrate. Neither call is bad alone.
  • Runaway loops, the 40th identical query_db call in a session.
  • Scope creep, an agent that touches one customer record is fine; one that touches thirty in a session needs approval.

Path-aware policy is what turns an audit trail into a control plane.