Invoke Kindo agents with the Responses API
Every agent you build in Kindo is invocable through
POST /v1/responses by passing its ID as the model:
{ "model": "agent/8e051857-978c-4207-8916-28a3d4c4d605", "input": "..." }The agent supplies the model, system prompt, and tools; you supply
the task. Because model is a field every OpenAI Responses client
can set, this works from stock SDKs with no code changes — the same
clients you already point at api.kindo.ai.
This page takes you from zero to a streamed agent run.
What you need
Section titled “What you need”-
A Kindo API key — see Authentication.
-
Your agent’s ID. Two ways to find it:
Terminal window # Alongside your model catalog (agents appear as agent/<agent-id>)curl "https://api.kindo.ai/v1/models?include_agents=true" \-H "Authorization: Bearer $KINDO_API_KEY"# Or from the agents list (returns agentId per agent)curl https://api.kindo.ai/v1/agents/list \-H "Authorization: Bearer $KINDO_API_KEY"You can also copy the agent ID from its URL in the Kindo Terminal.
Invoke the agent
Section titled “Invoke the agent”openai-python
Section titled “openai-python”import osfrom openai import OpenAI
client = OpenAI( base_url="https://api.kindo.ai/v1", api_key=os.environ["KINDO_API_KEY"],)
response = client.responses.create( model="agent/8e051857-978c-4207-8916-28a3d4c4d605", input="Triage INC-4821 and propose a remediation plan.", instructions="Keep the summary to one sentence.", # optional — appends after the agent's own prompt)
print(response.id, response.status)# resp_run_04f0faa6-2e66-4f5a-b49f-6a28daa58d9b in_progresscurl -X POST https://api.kindo.ai/v1/responses \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $KINDO_API_KEY" \ -d '{ "model": "agent/8e051857-978c-4207-8916-28a3d4c4d605", "input": "Triage INC-4821 and propose a remediation plan." }'The call returns immediately with an in-progress response — agent runs are long-horizon, so you stream or poll rather than block:
{ "id": "resp_run_04f0faa6-2e66-4f5a-b49f-6a28daa58d9b", "object": "response", "status": "in_progress", "model": "agent/8e051857-978c-4207-8916-28a3d4c4d605", "output": [], "conversation": { "id": "conv_cmqbjvxqv000001ac25z0pje6" }, "metadata": { "kindo_run_id": "04f0faa6-2e66-4f5a-b49f-6a28daa58d9b", "kindo_agent_id": "8e051857-978c-4207-8916-28a3d4c4d605" }}How your request composes with the agent
Section titled “How your request composes with the agent”input— delivered to the run. If the agent declares exactly one named input, your text binds to it; if it declares none, your text becomes the run conversation’s opening user message (visible context for every step). Agents with two or more named inputs cannot take freeform input — usePOST /v1/agents/runswith named inputs.instructions— optional; appended after the agent’s own system prompt.metadata— echoed back, merged with the run linkage keys.- Everything pinned by the agent’s stored configuration (
tools, non-"auto"tool_choice, sampling parameters,conversation,previous_response_id,background) is rejected with400 unsupported_parameternaming the field — nothing is silently dropped.
Stream the run live
Section titled “Stream the run live”Set stream: true to watch the run as it progresses. Each completed
step of the run arrives as a finished output item:
curl -N -X POST https://api.kindo.ai/v1/responses \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $KINDO_API_KEY" \ -d '{ "model": "agent/8e051857-978c-4207-8916-28a3d4c4d605", "input": "Triage INC-4821 and propose a remediation plan.", "stream": true }'event: response.createdevent: response.in_progressevent: response.output_item.added ← one pair per completed step itemevent: response.output_item.done (message text, tool calls, ...)event: response.completed ← carries the full final responsedata: [DONE]Notes on stream semantics:
- Items arrive whole, per completed step — you see each step’s output as the run advances, not token-by-token deltas. (Token-level streaming for agent runs is upcoming.)
- A failed run ends with
response.failed; a run cancelled from the Kindo Terminal ends with anerrorevent (code: "run_cancelled"). Every terminal path is followed bydata: [DONE]. - Streams are capped at 30 minutes (
error/code: "stream_timeout"). The run itself keeps executing — switch to polling below. - If you disconnect, nothing is lost: the run continues server-side and remains pollable.
Poll to completion (non-streaming)
Section titled “Poll to completion (non-streaming)”Without stream: true, take the id from the immediate response and
poll GET /v1/responses/{id} until the status is terminal:
import time
response = client.responses.create( model="agent/8e051857-978c-4207-8916-28a3d4c4d605", input="Triage INC-4821 and propose a remediation plan.",)
while response.status == "in_progress": time.sleep(3) response = client.responses.retrieve(response.id)
print(response.status) # completed | failed | cancelledprint(response.output_text) # the run's final answercurl https://api.kindo.ai/v1/responses/resp_run_04f0faa6-2e66-4f5a-b49f-6a28daa58d9b \ -H "Authorization: Bearer $KINDO_API_KEY"Statuses: in_progress → completed, failed, or cancelled.
Read the output
Section titled “Read the output”On a terminal status the response carries the run’s final output as standard Responses output items:
output— the final turn’s items (an assistantmessagewithoutput_textcontent; tool calls of the final turn where present).output_text— the concatenated final answer text.usage— token usage of the final turn.metadata.kindo_run_id/metadata.kindo_agent_id— run linkage. The run ID also works withGET /v1/runs/{runId}if you already integrate with the agents API.conversation.id— the run’s conversation. Read the full step-by-step transcript withGET /v1/conversations/{id}/items.
Current limitations
Section titled “Current limitations”Stated plainly, so you can design around them today:
- No request
toolson agent models. The agent’s tool set is pinned by its configuration; additive request tools are planned. - No
conversation/previous_response_idon agent models, and agent-run response IDs (resp_run_*) are not chainable viaprevious_response_id(you get404 previous_response_not_found). Conversation continuity for agent runs — follow-up turns to the same run conversation — is upcoming. - Version pinning is not available yet.
agent/<id>@<version>returns400 agent_version_pinning_unsupported; invocations always run the agent’s latest configuration. - Per-step tool-call detail in the stream is upcoming. Today the stream is step-granular (whole items per completed step); the final response carries the final turn’s items. The full transcript is always available via the run’s conversation items.
- Trigger-driven agents can’t be invoked directly
(
400 agent_not_invocable) — they run when their trigger fires.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
400 | model_not_found | Unknown, malformed, or inaccessible agent ID — indistinguishable from an unknown model on purpose. |
400 | agent_version_pinning_unsupported | agent/<id>@<version> — drop the version suffix. |
400 | agent_not_invocable | The agent has triggers and cannot be invoked directly. |
400 | agent_inputs_unmappable | The agent declares 2+ named inputs — use POST /v1/agents/runs. |
400 | unsupported_parameter | A request field conflicts with the agent’s pinned configuration; the message names the field. |
404 | previous_response_not_found | You passed a resp_run_* ID (or any non-stored response ID) as previous_response_id. |
404 | not_found | GET /v1/responses/resp_run_* for a run that doesn’t exist or that you cannot access. |
All errors use the standard Responses error envelope.
See also
Section titled “See also”- Responses API quickstart — point your SDK at Kindo.
- Request shape —
agent/<agent-id>in the field reference. - Model catalog —
discover agents with
include_agents=true. - Agents API — the control-plane surface (list agents, named-input runs, run results).