Skip to main content
    Ivy Biosciences Docs/Call the platform/API/Reference/Reference/Agent/POST /orchestrate

    POST /orchestrate

    Execute the biomedical agent

    Auth: optional. The route accepts anonymous calls; send an ivy_ API key (Authorization: Bearer ivy_… or X-Ivy-Api-Key) or a Clerk session JWT (Authorization: Bearer …) to call as your own account. See Authentication.

    Full Ivy agent loop: intent detection, dynamic tool selection, GPU execution via Modal, and multi-step reasoning. Signed-in callers resume a session by passing its sessionId; a guest's sessionId is ignored and every guest call starts a fresh, unsaved session. Unknown request fields are ignored. Streaming (default) emits named SSE events; non-streaming returns a summary JSON object. Approval gates (cost and safety checks on expensive or risky tools) are not enabled: every tool call proceeds automatically, for web, terminal and API callers alike. gatesAutoApproved lists each call that the gates would have stopped and that ran without an approval step. A session runs one turn at a time: a second request on the same session while a turn is running is refused with 409 TURN_IN_PROGRESS. Closing the connection stops the turn and cancels the jobs it started (a guest call's too), unless the request sent x-pleach-on-disconnect: continue. A turn stopped while the connection is still open (for example at the server time limit) emits a stopped event followed by done, or status: "stopped" in the JSON body.

    Trust and tool output. Tool results, tool errors and citations carry third-party data: database records, papers, web pages, files and computed outputs. Ivy is instructed to treat that content as data and never to follow instructions inside it. That is an instruction to the model, not a guarantee. Every tool call, tool_result, tool_error and citation is marked trust: "untrusted", and tool payloads name their source (the tool). Treat untrusted content as data in your own code and agent too: quote, display or cite it, and never act on instructions found in it.

    Request

    Headers

    x-pleach-depthinteger

    Delegation depth of this call. Omit it on a first call. An agent that calls this endpoint while running a turn for another agent call must send its own depth plus one, so a chain of agents calling agents stops after 4 hops. A value above 4 is refused with 400 DELEGATION_DEPTH_EXCEEDED; a value that is not a single non-negative integer is refused with 400 INVALID_DELEGATION_DEPTH. The header is a loop guard you set yourself, not a credential: it grants nothing.

    x-pleach-on-disconnectenum ("error" | "stop" | "continue")

    What closing the connection means for the turn (case-insensitive; also accepted as the on_disconnect query parameter). Absent or any other value (error): the turn stops and the jobs it started are cancelled (a guest call's too). stop: the same, recorded as a stop you asked for. continue: the turn does not stop; it finishes on the server within the request time limit, its jobs keep running, and nothing more is sent to the closed connection.

    Request body

    promptstring

    The user prompt for the biomedical agent

    modelstring

    Override the model for this turn. Signed-in callers who omit it get the model saved in their AI preferences, as in the web app. The override must belong to a model family your organization allows; otherwise the call returns 403 MODEL_FAMILY_NOT_PERMITTED. Guest calls always run on the guest model.

    sessionIdstring

    Resume an existing session (UUID v7). Signed-in callers only: a guest's sessionId is ignored and a fresh session is started

    projectIdstring (uuid)

    Signed-in callers only. Run the turn inside one of your projects, as a web chat in that project does. A project you cannot access returns 404 PROJECT_NOT_FOUND; a project-scoped API key can only name its own projects.

    campaignIdstring (uuid)

    Signed-in callers only. Run the turn inside one of your campaigns; the campaign's recent job history is added to the agent's context. A campaign you cannot access, or one outside projectId, returns 404 CAMPAIGN_NOT_FOUND.

    fileReferencesstring (uuid)[]

    Signed-in callers only. Ids of files you uploaded, attached to the prompt the way the web app's file picker attaches them. Any id that is not one of your files returns 404 FILE_NOT_FOUND.

    streamboolean

    Enable SSE streaming (default: true)

    outputFormatenum ("sse" | "text")

    Presentation of a streaming turn. sse (default) is the wire contract: named text/event-stream events, as documented below. text writes the same events as labelled plain text (text/plain) for someone reading curl -N output: boxed session / tool sections, status glyphs, the answer as prose, and a done summary — no SSE framing, colour only on a TTY and only when NO_COLOR is unset. The query string form ?format=text is equivalent, and ?format=sse pins the default. Content, events and billing are identical either way.

    diagnosticsboolean

    Opt-in headless diagnostics (IH-19): collect console breadcrumbs + a synthesized TurnReport for offline analysis. Default: false.

    toolsstring[]

    Allow-list. When present, only these tools may be offered to the model or run, plus a small exempt set the platform needs (review_tool_registry, get_data, sandbox_read). [] means no domain tools (exempt set only); omit for no restriction. Names are matched as canonical tool names after alias resolution (e.g. diffdock → diffdock_dock). Names must be tools this deployment offers: an unknown, deprecated or disabled name is a 400 UNKNOWN_TOOL (details.unknownTools echoes the first 20, details.unknownCount counts them all). At most 256 names of at most 128 characters each; more is a 400 INVALID_REQUEST. The list only narrows: it never admits a tool your tier or the guest tier refuses, and sub-agents inherit it.

    excludeToolsstring[]

    Deny-list. These tools are never offered to the model and a call to one is refused (tool error TOOL_EXCLUDED_BY_REQUEST) — including the exempt set if you name it. Same name matching and UNKNOWN_TOOL rule as tools. Wins over tools. Sub-agents inherit it. Withheld tools are reported in the response's withheldTools.

    maxCreditsnumber

    Most credits this response's model calls may debit. Each model call reserves the size of the largest call so far (at least 1 credit) before it is sent, and is refused when the credits spent plus every reservation of a call still running plus its own would exceed the cap, so calls made in parallel are checked together. Once one more tool round and the answer no longer fit, the tool loop stops and the answer is written from the results gathered; usage.llm.capped is then true. A call larger than every earlier one can overshoot by the difference. Counted: the model calls this response makes itself. Not counted or capped: GPU job credits (they appear in usage.gpu) and model calls a tool makes through a request to another API route. Guests may send it and it is accepted, but it is not applied: a guest call is bounded by the guest limits (the daily call quota and compute budget) instead. Must be a positive number, else 400 INVALID_REQUEST.

    Responses

    200 OK

    Agent execution response

    Response shape:

    sessionIdstring
    resumedboolean
    statusenum ("stopped")

    Present only when the turn was stopped before it finished (for example at the server time limit); content is then the partial answer. Absent on a completed turn.

    reasonenum ("user" | "timeout")

    Why the turn was stopped. Present only with status: "stopped".

    contentstring

    Ivy's full response text

    toolCallsobject[]
    artifactsobject[]
    citationsobject[]

    Source citations for the answer. Always present; an empty array means none were emitted. Folded from the turn's citation sets: a set marked final replaces the earlier ones, any other set is appended, deduplicated on source:identifier.

    recordobject

    Where to verify this session's audit record. Authenticated callers only: the key is absent for guest calls, whose sessions are not kept. Paths are relative to the API base URL.

    withheldToolsobject[]

    Tools the request's tools / excludeTools policy withheld this turn: offered-then-stripped intent or critical tools and refused calls, one entry per tool, at most 20 entries. Always present; an empty array means nothing was withheld.

    gatesAutoApprovedobject[]

    Tool calls this turn that an approval gate (cost or safety check) would have stopped and that ran without an approval step, because gates are not enabled. One entry per tool and gate, at most 64 entries. Names only. Always present; an empty array means no call would have been gated.

    gatesAutoApprovedDroppedinteger

    Present only when more distinct gated calls ran than gatesAutoApproved lists: how many were left off it.

    usageobject

    Credits this response's model calls debited from your balance (llm), and the credits held for the GPU jobs it submitted (gpu). Authenticated callers only: the key is absent for guest calls, which are not billed. Credits only: no dollar cost and no balance figure. A GPU hold is not the final charge: each job is charged when it finishes.

    stepsCompletedinteger
    messageCountinteger
    interruptsobject[]

    Approval gates the turn raised. Always present; an empty array means none fired. API and MCP callers have no interactive approver, so a gate auto-proceeds (outcome: auto_proceeded) and the tool runs.

    planobject

    The turn's plan. null means the turn made no plan; the key is absent when the turn ended before its plan could be read.

    subagentsobject[]

    Sub-agents the turn spawned. Always present; empty means none.

    correctionsobject[]

    Corrections applied to the answer during the turn. The answer text already reflects them; each entry names why. Always present; empty means none.

    modelSignalsobject

    Model retries, fallbacks to another model, and whether every model in the selected family failed.

    followUpobject

    Present when the turn ended while background jobs were still running (signed-in callers only). Poll pollUrl (GET /api/v1/orchestrate/{sessionId}) with the same credential; once the jobs finish, the answer composed from their results appears under resume. Guests get no handle: a guest session is not saved, so it cannot be fetched later.

    400 Bad Request

    INVALID_REQUEST: the body failed validation. UNKNOWN_TOOL: tools or excludeTools named a tool that does not exist. DELEGATION_DEPTH_EXCEEDED: x-pleach-depth is above 4. INVALID_DELEGATION_DEPTH: x-pleach-depth is not a single non-negative integer.

    Response shape: object

    401 Unauthorized

    Authentication required

    Response shape: object

    402

    INSUFFICIENT_CREDITS: a signed-in caller's credit balance cannot cover the turn. Nothing is run or charged.

    Response shape: object

    403 Forbidden

    TOOL_NOT_AVAILABLE_FOR_TIER: a guest call asked for a tool the guest tier does not include. Nothing is charged.

    Response shape: object

    404 Not Found

    Session not found (when a signed-in caller resumes with sessionId)

    Response shape: object

    409 Conflict

    TURN_IN_PROGRESS: a turn is already running on this session (one turn at a time per session and caller). Nothing is run or charged. Retry after the Retry-After header (seconds); the running turn may take longer.

    Response shape: object

    429 Too Many Requests

    Guest limit reached: GUEST_QUOTA_EXCEEDED (18 calls per day per IP) or GUEST_COST_LIMIT ($1.00 of compute per day per IP, metered from the measured usage of Ivy's model calls). Both reset at UTC midnight. The agent call limits below also apply.

    RATE_LIMITED: the burst rate limit (30 requests per 3 seconds for /orchestrate, 15 for /bench). A call made with an API key is counted against that key and against the key owner's total, wherever it is called from; a signed-in session is counted per user, and a call with no credential per IP. API_KEY_FAILURE_RATE_LIMITED: too many calls with an invalid or refused API key from this network. API_KEY_CONCURRENCY_LIMITED: this API key already has 5 agent turns in flight across /orchestrate and /bench. Each carries a Retry-After header.

    Response shape: object

    502 Bad Gateway

    Non-streaming only (stream: false): the turn produced no answer because of an upstream failure. The error code says why; a guest receives no internal detail.

    Response shape: object

    503 Service Unavailable

    GUEST_CAPACITY_REACHED: the shared guest pool is busy. Retry after the Retry-After header.

    Response shape: object

    curl -X POST 'https://ivybiosciences.com/api/v1/orchestrate' \
      -H "Authorization: Bearer $IVY_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
      "prompt": "Predict ADMET properties for aspirin"
    }'

    Was this page helpful?

    Loading...