Sessions

A session is a conversation with Claude Code or Codex in its own cloud environment. The agent keeps working when you close the page or disconnect.

Start a session

In the dashboard, describe the task on Home and click New session. From a terminal:

Shell
ellipsis -e cloud_agent_environment "Add an empty-body test in api-repo. Run it; do not commit."

From code:

import os
from ellipsis import Ellipsis

client = Ellipsis(api_key=os.environ["ELLIPSIS_API_TOKEN"])
handle = client.sessions.run(
    environment="cloud_agent_environment",
    budget={"session": 5},
    claude_code={
        "prompt": "Add an empty-body test in api-repo. Run it; do not commit."
    },
)
print(handle.id)

Replace cloud_agent_environment and api-repo with your environment and repository; without an environment, the session uses the default environment. budget caps the session at $5. Keep the session ID to check on it later. To set up the client, see the Python or TypeScript SDK and API authentication.

Follow the work

The dashboard and the CLI show messages and tool calls as they happen. To reattach the CLI to a running session, run ellipsis session get <session-id> --watch. From code, wait for the turn that answers your prompt:

session = handle.wait(timeout=900)
print(session.turn.status, session.turn.reason, session.turn.detail)

for record in client.sessions.records(handle.id):
    print(record.kind, record.payload)

wait() returns when the turn reaches a final status: completed, failed, stopped, or cancelled. Check turn.status before treating the task as done; reason and detail explain a failed or cancelled turn. A timeout stops your client from waiting, not the agent. To stream messages as they happen, see the Python or TypeScript SDK; for what each status means, see Lifecycle.

Retrieve a session

handle = client.sessions.handle("your-session-id")
print(handle.session.conversation.state, handle.session.turn)

Get a handle by ID at any time, for example after your application restarts. turn is the turn in progress, or the latest one when none is running.

Send a follow-up

In the dashboard, type in Reply to the agent... and click Send. In the CLI, type in the session view. From code:

message = handle.send("Add a test for an invalid content type too.")
session = handle.wait(timeout=900)
print(message.turn_id, session.turn.status)

A follow-up continues the same conversation and workspace. The message gets its turn the moment it is received, and wait() then waits on that turn; a message sent while a turn is running is answered after it. Only the person who started a session can message it. Sessions started by a mention take replies in their GitHub, Slack, or Linear thread. A closed session can't take follow-ups; conversation.prompting says whether a message would be accepted, see Lifecycle.

Run a one-off task

task = client.sessions.run(
    environment="cloud_agent_environment",
    claude_code={
        "prompt": "Run request-validation tests in api-repo and report failures."
    },
    conversation={"interactive": False},
)
result = task.wait(timeout=900)
print(task.id, result.turn.status, result.conversation.state)

Set conversation.interactive to false when you won't send follow-ups. The conversation closes when its turn ends and its environment is deleted; its messages and results stay available. To save a task and run it again or on a schedule, use Agents.

Inspect the result

diff = client.sessions.diff(handle.id)
for file in diff.files:
    print(file.full_name, file.path, file.patch)
print("Omitted paths:", diff.omitted_paths)

git = client.sessions.git(handle.id)
for repo in git.repos:
    print(repo.full_name, repo.commits, repo.prs)

Get the session's uncommitted changes and the commits and pull requests it made. Files left out of the diff are listed in omitted_paths.

Cost and records

session = handle.refresh()
print("Cost (USD):", session.cost.total / 100_000)
print("Budget (USD):", session.budget)

cost.total is in thousandths of a cent, so divide by 100,000 for dollars. budget is in dollars, and follow-ups share it. Each turn carries its own cost and tokens; list them with GET /v1/sessions/{session_id}/turns. See Pricing for rates, or download the session history.

Stop a session

Click Stop in the dashboard. In the CLI, type /stop in the session view or run ellipsis session stop <session-id>. From code:

session = handle.stop()
print(session.turn.status, session.turn.stopped)

Stopping ends the running turn with stopped, not the conversation: the session can still take follow-ups. Stopping a session with no turn pending or running fails with 409. Disconnecting doesn't stop the agent.

On this page

Schedule a demo