deco Studio

Call an Agent from Your App

Drive a Studio agent from an external system with a scoped API key — create a thread, run the agent, stream the response, and read the thread back

Overview

You can drive any Studio agent from an external system — a chatbot backend, a webhook handler, a CRON job — using a scoped API key over plain HTTP. The flow is the same one the Studio web client uses:

  1. Create a thread for the agent.
  2. Post a message to enqueue a run.
  3. Stream the agent’s response in real time.
  4. Read the full thread back later from durable storage.

No SDK is required — every step is a normal HTTP request authenticated with Authorization: Bearer <api-key> .

Create the API key

The fastest way is from the agent’s Connect dialog → Call from your appCreate API key. It mints a key scoped to exactly the tools this flow needs and shows it once.

To create it programmatically, call the API_KEY_CREATE tool with these permissions:

 {
  "name": "chat-bridge-my-agent",
  "permissions": {
    "self": [
      "COLLECTION_THREADS_CREATE",
      "COLLECTION_THREADS_GET",
      "COLLECTION_THREAD_MESSAGES_LIST",
      "COLLECTION_THREADS_LIST"
    ]
  },
  "expiresIn": 7776000
} 
Field Type Notes
name string Human-readable label
permissions { [resource]: string[] } self holds the management tools above
expiresIn number Lifetime in seconds (here, 90 days). Omit for no expiry

expiresIn is a number of seconds, not a string. The key value is returned only once, at creation — store it immediately.

The run and stream endpoints below only require that the key belongs to a member of the org, so no connection-scoped grant is needed. The self permissions are only what the thread read/write tools require.

Endpoints

All paths are org-scoped, where :org is your organization slug.

Step Method & path
Create thread POST /api/:org/tools/COLLECTION_THREADS_CREATE
Run agent POST /api/:org/decopilot/threads/:threadId/messages
Stream GET /api/:org/decopilot/threads/:threadId/stream
Read thread POST /api/:org/tools/COLLECTION_THREAD_MESSAGES_LIST
Thread status POST /api/:org/tools/COLLECTION_THREADS_GET

1. Create a thread

The virtual_mcp_id is the agent (Virtual MCP) id — find it in the agent’s URL or via COLLECTION_CONNECTIONS_LIST .

 curl -X POST "$MESH_BASE_URL/api/$MESH_ORG/tools/COLLECTION_THREADS_CREATE" \
  -H "Authorization: Bearer $MESH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "data": { "title": "Support chat", "virtual_mcp_id": "'"$MESH_AGENT_ID"'" } }'
# → { "item": { "id": "thrd_...", "status": "...", ... } } 

Use the returned item.id as :threadId for the next steps. (You may also supply your own data.id .)

2. Run the agent

This enqueues a run and returns 202 immediately — the body carries no output.

 curl -X POST "$MESH_BASE_URL/api/$MESH_ORG/decopilot/threads/$THREAD_ID/messages" \
  -H "Authorization: Bearer $MESH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{ "role": "user", "parts": [{ "type": "text", "text": "Hello!" }] }],
    "agent": { "id": "'"$MESH_AGENT_ID"'" },
    "tier": "smart"
  }'
# → 202 { "taskId": "thrd_..." } 

The request body is validated strictly — send only messages , agent , and optional tier / temperature . Exactly one non-system message is allowed per call. The thread id lives in the URL; don’t also put a mismatched thread_id in the body.

3. Stream the response

The agent output is a Server-Sent Events stream (AI SDK UI-message chunks), backed by NATS JetStream server-side.

 curl -N "$MESH_BASE_URL/api/$MESH_ORG/decopilot/threads/$THREAD_ID/stream" \
  -H "Authorization: Bearer $MESH_API_KEY" \
  -H "Accept: text/event-stream" 

Open the stream before posting the message so you don’t miss early chunks. The browser’s native EventSource cannot send an Authorization header — use fetch() and read the response body as a stream instead.

The stream is an ephemeral live buffer (~5 minutes retention), not the system of record. For the durable transcript, read the thread (step 4).

4. Read the thread back

The authoritative, durable transcript is available any time:

 curl -X POST "$MESH_BASE_URL/api/$MESH_ORG/tools/COLLECTION_THREAD_MESSAGES_LIST" \
  -H "Authorization: Bearer $MESH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "thread_id": "'"$THREAD_ID"'", "limit": 200 }' 

Poll run progress with COLLECTION_THREADS_GET ( { "id": "<threadId>" } ) and watch status move from in_progress to completed or failed .

Scoping & security

  • A key is bound to a single organization (embedded at creation). The :org in the path must match that org’s slug.
  • The self thread permissions gate the read/write tools, but the run and stream endpoints authorize on org membership alone — so any valid org key can drive agents. Treat these keys like any production credential: name them per integration, set an expiry, and rotate by deleting ( API_KEY_DELETE ) and re-creating.

Found an error or want to improve this page?

Edit this page