Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.karta.sh/llms.txt

Use this file to discover all available pages before exploring further.

A session is a lightweight orchestration handle. It carries metadata, the list of participants, the current agent, and any pending approval — but it holds no messages. Conversation history lives in the harness. That single fact explains most of how sessions behave.

A session is a handle, not a store

from karta import Karta

app = Karta()
session = app.session(metadata={"customer_id": "abc123"})

session.send_sync("I need help with my order")
session.send_sync("It's order #12345")     # same thread; harness has the history
What the handle tracks:
FieldMeaning
idThe session identifier (maps to a harness thread under the hood).
metadataArbitrary key/values you set — route and look sessions up by these.
participantsThe humans and AIs in the conversation.
current_agentWhich agent is handling turns right now.
statusactive, etc.
pending_inputA request_id awaiting an approval decision, if any.
permission_modeHow approval prompts are handled for this session.
Because the handle is cheap and the harness is the source of truth, resuming a session is just looking it up again — typically by the metadata you tagged it with.
# Later, same process or a new one:
session = app.session(metadata={"customer_id": "abc123"})
session.send_sync("Any updates?")

Participants and attribution

A session isn’t limited to one human and one bot. Multiple participants — humans and AIs — can share a session, and every message is attributed to its sender.
from karta import Karta, HumanAgent

app = Karta()
session = app.session()

alice = HumanAgent(name="alice", display_name="Alice Chen")
bob   = HumanAgent(name="bob",   display_name="Bob Park")

session.send_sync("I need help with deployment", participant=alice)
session.send_sync("I can help — what's the error?", participant=bob)
This is what makes shared inboxes, human-in-the-loop hand-ins, and agent-to-agent collaboration first-class rather than bolted on. Delivery and fan-out across participants — including across Karta instances — is the job of the gateway.

Agent handoff

A session has a current agent, and you can hand off mid-conversation to a specialist. The handoff fires an agent.handoff lifecycle hook.
session = app.session(metadata={"customer_id": "abc123"})
session.send_sync("I need help with my order")     # → default agent
session.current_agent = app.agents["billing"]       # handoff
session.send_sync("Check invoice #789")             # → billing agent
See Agents for how 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:
async for event in session.stream_pending_input("approve_once", request_id=req_id):
    ...
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.

Agents

Discovery, routing, and handoff.

Gateway

Fan-out delivery to participants, in-process and across instances.