Skip to content

Quickstart

Before you begin

  1. Make sure your organization has at least one agent that you can run. If it has none, create one in the app or with Create an agent.
  2. Install the tools for the language you use: curl and jq, the anthropic Python package, or the @anthropic-ai/sdk Node package.
If you know Anthropic’s quickstart, the main differences are that you pick an existing agent and don’t create an environment. Step 2 lists your agents, and sessions use env_default. For every other difference, see Coming from Anthropic’s API.
  1. Create a key and set your host

    In the app, go to Settings > API > Task keys > New key and create a Personal key with the default capabilities. Use a personal key because your own code calls agents on your behalf. If an automation calls them, see Choose a key. Copy the key, because it is shown only once. In every shell you use, export CONTEXT_BASE_URL and CONTEXT_API_KEY as shown in the cURL tab. The Python and TypeScript clients read both from the environment. Set CONTEXT_BASE_URL to the host without /v1, because the SDKs add /v1 themselves.

    cURL
    export CONTEXT_BASE_URL="https://api.context.ai"
    export CONTEXT_API_KEY="tsk_..."
    Python
    import os
    from anthropic import Anthropic
    client = Anthropic(
    base_url=os.environ["CONTEXT_BASE_URL"],
    api_key=os.environ["CONTEXT_API_KEY"],
    max_retries=0,
    )
    TypeScript
    import Anthropic, { toFile } from "@anthropic-ai/sdk"
    import { readFile } from "node:fs/promises"
    const client = new Anthropic({
    baseURL: process.env.CONTEXT_BASE_URL,
    apiKey: process.env.CONTEXT_API_KEY,
    maxRetries: 0,
    })
  2. Pick an agent

    List the agents your key can run. In the last line, replace the example ID with the ID of the agent you want.

    cURL
    curl -sS "$CONTEXT_BASE_URL/v1/agents" -H "x-api-key: $CONTEXT_API_KEY" | jq -r '.data[] | "\(.id) \(.name)"'
    export AGENT_ID="6f1c2a9e-0d4b-4c57-9a3e-2b7d8e1f4c60"
    Python
    for agent in client.beta.agents.list():
    print(agent.id, agent.name)
    agent_id = "6f1c2a9e-0d4b-4c57-9a3e-2b7d8e1f4c60"
    TypeScript
    for await (const agent of client.beta.agents.list()) console.log(agent.id, agent.name)
    const agentId = "6f1c2a9e-0d4b-4c57-9a3e-2b7d8e1f4c60"
  3. Upload a file

    Make a small CSV and upload it. The file goes to your Drive in the app.

    cURL
    printf 'city,population\nTokyo,37400000\nDelhi,31000000\n' > cities.csv
    export FILE_ID=$(curl -sS -X POST "$CONTEXT_BASE_URL/v1/files" -H "x-api-key: $CONTEXT_API_KEY" \
    -F "file=@cities.csv;type=text/csv" | jq -r .id)
    Python
    from pathlib import Path
    Path("cities.csv").write_text("city,population\nTokyo,37400000\nDelhi,31000000\n")
    file_id = client.beta.files.upload(file=Path("cities.csv")).id
    TypeScript
    import { writeFile } from "node:fs/promises"
    await writeFile("cities.csv", "city,population\nTokyo,37400000\nDelhi,31000000\n")
    const fileId = (await client.beta.files.upload({
    file: await toFile(await readFile("cities.csv"), "cities.csv", { type: "text/csv" }),
    })).id
  4. Create a session with the file

    Create a session that runs the agent with the file attached. Set environment_id to env_default to run it in a cloud sandbox that Context starts for the session. For more information, see Environments. The session starts idle. The response lists the file under resources with mount_path: "inputs/cities.csv", which is where the session finds it. If the agent isn’t in a workspace you work in, the request returns 400 with a message that names the agent; create the agent with metadata.workspace_id or pick another agent.

    cURL
    export SESSION_ID=$(curl -sS -X POST "$CONTEXT_BASE_URL/v1/sessions" -H "x-api-key: $CONTEXT_API_KEY" \
    -H "content-type: application/json" \
    -d "{\"agent\": \"$AGENT_ID\", \"environment_id\": \"env_default\", \"title\": \"Quickstart\",
    \"resources\": [{\"type\": \"file\", \"file_id\": \"$FILE_ID\"}]}" | jq -r .id)
    Python
    session = client.beta.sessions.create(
    agent=agent_id,
    environment_id="env_default",
    title="Quickstart",
    resources=[{"type": "file", "file_id": file_id}],
    )
    print(session.id, session.resources[0].mount_path)
    TypeScript
    const session = await client.beta.sessions.create({
    agent: agentId,
    environment_id: "env_default",
    title: "Quickstart",
    resources: [{ type: "file", file_id: fileId }],
    })
    console.log(session.id, session.resources[0].mount_path)
  5. Open the stream, then send a message

    The stream carries only what happens after it opens, so open it first. With cURL, run the stream in one terminal and send the message from a second terminal that has the same variables set. The agent has finished replying when the stream sends a session.status_idle event whose stop_reason.type isn’t requires_action. If the agent asks to run a tool that needs your approval, follow the tool approvals playbook.

    cURL
    # Terminal 1: watch the stream
    curl -sSN "$CONTEXT_BASE_URL/v1/sessions/$SESSION_ID/events/stream" -H "x-api-key: $CONTEXT_API_KEY"
    # Terminal 2: send the message
    curl -sS -X POST "$CONTEXT_BASE_URL/v1/sessions/$SESSION_ID/events" -H "x-api-key: $CONTEXT_API_KEY" \
    -H "content-type: application/json" \
    -d '{"events": [{"type": "user.message", "content": [{"type": "text", "text": "Read inputs/cities.csv and name the largest city."}]}]}'
    Python
    with client.beta.sessions.events.stream(session.id) as stream:
    client.beta.sessions.events.send(
    session.id,
    events=[{"type": "user.message", "content": [{"type": "text", "text": "Read inputs/cities.csv and name the largest city."}]}],
    )
    for event in stream:
    if event.type == "agent.message":
    print("".join(block.text for block in event.content))
    if event.type == "session.status_idle" and event.stop_reason.type != "requires_action":
    break
    TypeScript
    const stream = await client.beta.sessions.events.stream(session.id)
    await client.beta.sessions.events.send(session.id, {
    events: [{ type: "user.message", content: [{ type: "text", text: "Read inputs/cities.csv and name the largest city." }] }],
    })
    for await (const event of stream) {
    if (event.type === "agent.message") console.log(event.content.map((block) => block.text).join(""))
    if (event.type === "session.status_idle" && event.stop_reason.type !== "requires_action") break
    }

    The agent replies with something like Tokyo is the largest city, with 37,400,000 people. With cURL, terminal 1 prints one frame per event. The reply arrives as an agent.message frame, and a session.status_idle frame marks the end of the reply. Each frame has id, event and data lines, as shown in Stream events.

  6. Archive the session and delete the file

    Archiving ends the session and returns it with status terminated. Its history stays readable. You can delete a file after every session that uses it is archived. Deleting it earlier returns 400. Deleting a file is permanent.

    cURL
    curl -sS -X POST "$CONTEXT_BASE_URL/v1/sessions/$SESSION_ID/archive" -H "x-api-key: $CONTEXT_API_KEY" | jq -r .status
    curl -sS -X DELETE "$CONTEXT_BASE_URL/v1/files/$FILE_ID" -H "x-api-key: $CONTEXT_API_KEY"
    Python
    print(client.beta.sessions.archive(session.id).status) # terminated
    client.beta.files.delete(file_id)
    TypeScript
    console.log((await client.beta.sessions.archive(session.id)).status) // terminated
    await client.beta.files.delete(fileId)

What happened in this quickstart

  • The session is a task in the Context app. Its transcript is there, under the title you gave it.
  • The upload went to your Drive in the app. The session reads it from its inputs/ folder.
  • The stream was live from the moment it opened and carried nothing from before. List events returns the whole history.
  • Archiving ended the session and kept its history readable. To remove a session for good, use Delete a session with a key that has sessions:delete.

Next steps

  • Sessions explains what each session status means and how to rename and archive a session.
  • Stream events shows which frames the stream sends, how it ends and how to reconnect without losing events.
  • The tool approvals playbook shows how to approve or deny a tool call when a session goes idle with requires_action.