Skip to main content

Calling agents

Applications invoke an agent ID. An employee ID identifies shared configuration; it is not a runnable route. Use an agent you created or one your operator made available, and verify it with Listing agents.

Choose the interface

InterfaceAgent selectorText in a successful non-streaming response
Python client.messages.create(...)agent_id="intake"response.text (SDK helper)
POST /v1/messagesmetadata.agent_idText blocks in content[]
POST /v1/chat/completionsmodel: "intake" for a registered agentchoices[0].message.content
POST /agents/v1/intake/chatAgent route ID in the pathresponse
POST /agents/v1/intake/jobsAgent route ID in the pathReturns a job receipt; retrieve the result later

These endpoints do not share one request or response schema. In particular, the Python parameter agent_id becomes metadata.agent_id on the Messages wire format. A top-level agent_id is not valid for /v1/messages.

Messages-compatible request

Set LIBRA_OS_URL to your server URL and LIBRA_OS_API_KEY to an authorized bearer credential. This example assumes an agent named intake already exists:

curl --fail-with-body -sS "$LIBRA_OS_URL/v1/messages" \
-H "Authorization: Bearer $LIBRA_OS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "intake",
"max_tokens": 500,
"metadata": {"agent_id": "intake"},
"messages": [{"role": "user", "content": "What can you help me with?"}]
}'

Here metadata.agent_id selects the behavior and model repeats the agent ID so its configured model can be used. A supported provider model ID in model can instead override the answer model for that call; it does not select the agent or change all planner/skill tiers. Omitting metadata.agent_id selects the server's default agent, even if model looks like another agent ID.

To read text from the raw response:

text = "".join(
block.get("text", "")
for block in response["content"]
if block.get("type") == "text"
)

Keep non-text blocks when using tools. Do not parse the entire content array as a string or discard tool results your application needs.

Native chat request

curl --fail-with-body -sS "$LIBRA_OS_URL/agents/v1/intake/chat" \
-H "Authorization: Bearer $LIBRA_OS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"message":"What can you help me with?"}'

Native chat uses message for a simple text turn and returns fields such as response, agent_id, conversation_id, retrieved_chunks, and grounding. Save the returned conversation_id and send it with subsequent native turns to continue that thread.

Authentication, context, and memory

The credential identifies the caller and its permissions. A conversation ID identifies a thread. An agent ID selects executable behavior. None substitutes for another.

With the Python Messages API, sending message history explicitly is a portable way to continue a conversation. For stored Messages threads, the server also accepts metadata.conversation_id; use a stable, authorized ID and follow the endpoint's history behavior. Observational memory is separately enabled and identity-scoped. See Managing memory.

Backend integrations serving several people must use the deployment's authorized identity mechanism. X-End-User is honored only for callers with the relevant impersonation capability. Never treat an employee ownership link or a client-supplied ID as a grant of access.

Handle outcomes

OutcomeWhat to check
401 / 403Credential validity and permission for the endpoint, agent, and resource.
404Correct route/agent ID and visibility; an upstream model can also be unavailable.
409 creating an agentThe name may already exist; reuse or deliberately update the agent.
426 on /v1/agentsSupply the managed-agent beta header or use the SDK.
Answer has no sourcesCheck knowledge bindings, ingestion, retrieval capabilities, and grounding metadata.
Tool action awaits approvalFollow the action's decision/execution status; a completed chat is not evidence that the action executed.

For asynchronous progress, reconnect rules, and job statuses, use the background-task guide.