Skip to main content
A session is a lightweight orchestration handle. It carries metadata, the list of participants, the current sub-agent, and any pending approval. The session record is not the message store. Conversation history lives with the harness and the transcript Karta records for the session. That single fact explains most of how sessions behave.

A session is a handle, not a store

What the handle tracks: Because the handle is cheap and the harness is the source of truth, resuming a session means addressing an existing one by its session_id - not by its metadata. app.session(metadata=...) always mints a new session, so hold onto the Session you created (or stash its id) and resume by that.
Over HTTP the same thing is create-with-session_id (or fetch-then-send); see the Sessions API.

Sessions run inside a karta

Kartas & memory covers this model in full; here is how it maps onto sessions. For a user-facing product, each stable user id can get its own durable karta - a life coach or tutor that remembers one person across visits. Use verified identity when the agent needs to act on per-user data or credentials. Soft or anonymous ids can provide continuity, but they are advisory only; any browser page can set them, so your backend must not treat them as proof of who the user is. To have a team work with a roster of virtual employees, name stable agent_instance_id values from your backend. One team might use auditor-west, auditor-east, reviewer-risk, reviewer-finance, and reviewer-compliance as five separate kartas. Each karta has its own files, sessions, memory, and working style; each acting person is still attributed per turn for usage and per-seat caps. How you name a shared karta depends on the surface:
  • From your backend (server-to-server with an API key, or a backend-minted session token), pass it in session metadata:
  • In an embedded widget, configure the stable karta id on the embed key itself (Embed keys -> the key -> “Karta ID”). Every widget session from that key then joins that virtual employee, backend worker, or other deliberately shared karta.
agent_instance_id is the API field behind the public karta noun. It is trusted only when it comes from your backend or the embed key’s server-side config. Public browser metadata cannot redirect a widget into another shared karta.

Participants and attribution

A session is not limited to one human and one bot. Multiple participants - humans and AIs - can share a session, and every message is attributed to its sender.
This supports shared inboxes, human-in-the-loop handoffs, and agent-to-agent collaboration. Karta delivers each event to every participant in the session - sending or streaming through a session does this fan-out for you. When you build agent-to-agent topologies explicitly, the gateway API exposes the same submit-and-deliver surface directly.

Sub-agent handoff

A session has a current sub-agent, and you can hand off mid-conversation to another sub-agent. The handoff fires an agent.handoff lifecycle hook.
See Sub-agents for how sub-agents are discovered and routed.

Pending input & approvals

When the harness needs permission - to run a tool, write a file - it emits an input_required event and the session records pending_input. You resolve it with a decision:
Over HTTP this is the inputs endpoint; decisions are approve_once, approve_session, or deny. How aggressively Karta prompts is governed by permission_mode and the input_required_policy config.

Over HTTP

The same model is exposed on the wire: create a session, send (or stream) messages, resolve inputs. See the Sessions and Messages API reference.

Sub-agents

Discovery, routing, and handoff.

Streaming events

The typed events every message and approval flows through.