Session Management

Sessions are the operational boundary around agent work. Every task an agent performs runs inside a session that declares what the agent intends to do, which tools it can use, how long it has, and how many calls it can make. Think of a session as a work order: scoped, budgeted, and auditable.

For a hands-on walkthrough, see Your First Session. This guide covers the full model.

Session Anatomy

Field

Type

Purpose

session_id

UUID

Unique identifier, passed as x-arbiter-session header

agent_id

UUID

The agent this session belongs to

declared_intent

string

Free-form description of the planned work

authorized_tools

string[]

Tools the agent can call (anything else is denied)

time_limit

duration

How long before the session expires

call_budget

integer

Maximum tool calls before exhaustion

rate_limit_per_minute

integer

Optional per-minute call cap

data_sensitivity_ceiling

enum

Maximum data sensitivity tier: public, internal, confidential, restricted

status

enum

Active, Closed, or Expired

Creating Sessions

$ curl -s -X POST http://localhost:3000/sessions \
  -H "x-api-key: arbiter-dev-key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "'$AGENT_ID'",
    "declared_intent": "analyze Q4 transaction patterns for risk assessment",
    "authorized_tools": ["query_transactions", "get_account_summary", "generate_risk_report"],
    "time_limit_secs": 3600,
    "call_budget": 200,
    "rate_limit_per_minute": 30,
    "data_sensitivity": "internal"
  }'

If you omit optional fields, Arbiter uses defaults from the [sessions] config section:

  • time_limit_secs defaults to default_time_limit_secs (3600)

  • call_budget defaults to default_call_budget (1000)

Enforcement Chain

On every proxied request, the session middleware runs five checks in order:

  1. Existence and status. The session must exist and be Active. Expired or Closed sessions return 408.

  2. Agent binding. The JWT’s agent ID must match the session’s agent_id. No sharing sessions between agents.

  3. Tool whitelist: the tool being called must appear in authorized_tools. Missing tools get 403.

  4. Budget: if calls_made >= call_budget, the session is exhausted. Returns 429.

  5. Rate limit: if the current-window call count exceeds rate_limit_per_minute, returns 429.

If all checks pass, the call counter increments and the request proceeds.

Budget Warnings

When remaining budget or time drops below the warning threshold (default 20%, configurable via warning_threshold_pct), Arbiter adds warning headers to the response:

X-Arbiter-Warning: budget_remaining=15, budget_total=200
X-Arbiter-Warning: time_remaining_secs=180, time_limit_secs=3600

Agents or their orchestrators can use these to wrap up gracefully before the hard limits kick in.

Data Sensitivity Ceilings

Sessions carry a data_sensitivity_ceiling that sets the maximum tier of data the session can access:

Tier

Description

public

Open data, no restrictions

internal

Organization-internal, not for external sharing

confidential

Sensitive business data

restricted

Regulated data (PII, PHI, financial)

Tiers are ordered. A session with an internal ceiling cannot access confidential or restricted data.

Concurrent Session Limits

The max_concurrent_sessions_per_agent setting (default 10) caps how many active sessions one agent can hold simultaneously. This closes a specific attack vector: a compromised agent opening many sessions to multiply its effective call budget.

When an agent hits the cap, session creation returns HTTP 429:

{
  "error": "TooManySessions",
  "message": "agent has 10 active sessions (max: 10)"
}

Existing sessions keep working. The cap is enforced at creation time only.

Session Lifecycle

              create
                │
                v
             Active ──────> Expired (time_limit exceeded)
                │
                │  DELETE /sessions/{id}
                v
              Closed

Active sessions transition to Expired automatically when the time limit passes. You can also close a session explicitly through the API, which is the clean way to signal that a task is done.

Configuration Defaults

These go in the [sessions] section of arbiter.toml:

[sessions]
default_time_limit_secs = 3600
default_call_budget = 1000
warning_threshold_pct = 20.0
max_concurrent_sessions_per_agent = 10
rate_limit_window_secs = 60
cleanup_interval_secs = 60
escalate_anomalies = false

See Configuration Reference for full descriptions of each option.

Next Steps