Agents APISessions
Run and continue
Give an agent a task, know when it's done, and keep the conversation going.
Sessions and runs
A session is one agent with one conversation and one workspace. A run is one piece of work inside it: the agent picks up a message, uses tools until it has an answer, and stops. A message sent to an idle session starts a new run. A message sent during a run joins it.
Start a task
create() returns straight away with status provisioning. The first message runs as soon as the sandbox is ready, usually within seconds. Follow events until run.completed to know the task is done:
import { LatentStack } from "@latentcode/sandbox-agents"
const client = new LatentStack({ apiKey: process.env.LS_API_KEY! })
const sessions = client.agents.sessions
const session = await sessions.create({
agent: {
model: "bedrock/us.anthropic.claude-sonnet-5",
instructions: "Answer briefly.",
// An empty sandbox has nothing to protect, so let the agent run commands without asking.
permissions: [{ action: "bash", effect: "allow" }],
},
input: "Write a Python script that prints the first 10 prime numbers, run it, and show me the output.",
})
for await (const event of sessions.events(session.id)) {
if (event.type === "tool.called") console.log("tool:", event.data?.tool)
if (event.type === "text.ended") console.log(event.data?.text)
if (event.type === "run.completed" || event.type === "run.failed") break
}Every run ends with one of two events:
run.completed: the agent finished, or you cancelled the run. Its answer is in thetext.endedevents before it.run.failed: the run stopped on an error, such as the model provider failing.data.errorsays why. The session is still usable: send another message to retry.
wait() returns on the first settled status. Right after create(), a session is briefly idle before its first message starts, so wait() can return before the work has begun. Use wait() for status changes you started yourself, like a pause, and events for runs.Continue the conversation
Send another message to the same session. It starts a new run with everything that came before. Pass the session's last_seq as after to read only what's new.
const { last_seq } = await sessions.get(session.id)
await sessions.message(session.id, "Now make it print the first 20.")
for await (const event of sessions.events(session.id, { after: last_seq })) {
if (event.type === "text.ended") console.log(event.data?.text)
if (event.type === "run.completed" || event.type === "run.failed") break
}
await sessions.delete(session.id)Steer or queue
A message sent during a run steers it: the agent takes it into account without starting over. To add work for afterwards instead, send it with delivery: "queue". It becomes a new run when the current one completes.
// Joins the run in progress: the agent adjusts without starting over.
await sessions.message(session.id, "Make every poem a haiku, and keep going until all five files exist.")
// Runs after the current run finishes.
await sessions.message(session.id, "Then list the files you created, one per line.", { delivery: "queue" })message taken: "steer" ← the first task
message taken: "steer" ← joined the run in progress
message taken: "queue" ← ran after it
All five haiku files are done — poem1.md through poem5.md, each a short sea-themed haiku.
poem1.md
poem2.md
…Cancel a run
Cancelling stops the current run. The session and everything done so far stay, and the next message starts a new run.
await sessions.cancel(session.id)
const settled = await sessions.wait(session.id)
console.log(settled.status) // "idle": the session is still there for the next messageTo end the session itself, delete it. See Manage sessions.
Coming back later
You don't need to keep a connection open. Store the session id, and the last event number you handled, with your own data. Later, send a message and read events after that number. If the session paused while you were away, the message wakes it with its files and conversation intact. The long-lived assistant example does exactly this.