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.