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.
What a session accumulates
Section titled “What a session accumulates”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).
What policy sees
Section titled “What policy sees”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. therate_limit_tool_per_sessiontemplate) 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.
What path-aware rules look like
Section titled “What path-aware rules look like”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.
Why it matters
Section titled “Why it matters”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_dbcall 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.
Next steps
Section titled “Next steps”- Rule reference — the trajectory and usage rule kinds
- The audit trail — how sessions are recorded and queried