Sessions
Sessions, lifecycle, and per-session file access scoping.
A session is one agent process in a per-session sandbox, running inside your dedicated pod. Sessions are independent: each has its own conversation history, its own file-access scope, its own busy state.
POST /v1/sessions
Create a session.
Request body (all fields optional):
| Field | Type | Default | Description |
|---|---|---|---|
persistent | bool | false | If false, session auto-destroys 5 minutes after the last response completes. If true, lives until ttl expires or you DELETE it. |
ttl | int (seconds) | 14400 (4h) | Hard upper bound on session lifetime. |
metadata | object | {} | Free-form key/value attached to the session. Returned on GET. |
file_access | object | full workspace | Restrict which files the agent (and your file API calls) can see. See File access. |
model | string | tenant default | Catalog model name (pokee-isaac-high-reasoning, pokee-isaac, plus any per-tenant additions). Locked at session create — every turn in this session runs on the chosen model. See Models and pricing. |
tools | array | [] | OpenAI-shape function definitions the agent can call. The tool call surfaces as a tool_call.requested SSE event during a turn; you POST the result to /v1/sessions/{id}/tool_results to resume. See Tool calling. Locked at create time. |
Response (201 Created): full session record.
{
"id": "sess_a86118c06688",
"created_at": 1777222996.07,
"last_activity": 1777222996.07,
"busy": false,
"persistent": false,
"ttl": 14400,
"status": "ready",
"metadata": {},
"file_access": {"read": [""], "write": [""]}
}GET /v1/sessions
List all sessions for the tenant. Returns [<session_record>, ...].
GET /v1/sessions/{id}
Get a session record. Returns 404 if the session has been destroyed. Watch metadata for tool-specific status fields.
DELETE /v1/sessions/{id}
Destroy a session. Returns 204. Idempotent for an already-destroyed session (returns 404).
DELETE /v1/sessions
Bulk delete with query params:
| Param | Description |
|---|---|
status=idle | Only destroy idle (non-busy) sessions |
older_than=2h | Destroy sessions inactive for at least N (s/m/h suffix; combinable: 1h30m) |
Response: {"deleted": <count>}.
File access
By default a session sees the entire workspace. To restrict, pass file_access at create time:
{
"file_access": {
"read": ["projects/my-project", "shared/templates"],
"write": ["projects/my-project/output"]
}
}Rules:
- Paths are workspace-relative. No leading slash.
- Empty string
""= whole workspace (the default). writeimpliesread— no need to list a path twice.- The session's own dir
.sessions/{session_id}/is always included automatically. - Effective scope is immutable for the session's lifetime. To change it, destroy and recreate.
Enforcement is at two layers; both reject out-of-scope access but surface it differently:
- The agent's filesystem (its own Bash, Read, Write tool calls) — per-session bwrap mount namespace. Out-of-scope paths simply don't exist in the namespace; any operation returns
ENOENT("No such file or directory").lsof a parent dir won't list out-of-scope siblings either. - The HTTP file API (
GET / PUT / DELETE /v1/sessions/{id}/files/{path}) — explicit scope check, returns403 Forbiddenwith{"error":"Forbidden","message":"'<path>' not in session scope"}. Use the 403 to detect a misconfigured client; treat it like a 404 for security purposes — neither response confirms or denies the existence of files outside your scope.
Defaulted (whole-workspace) sessions don't trigger either layer because their scope is "" (everything). To get strict isolation between sessions, create them with explicit file_access paths.