Agents API (Beta)
Run LibreChat agents and deliver authenticated events through programmatic APIs
Beta Feature
The Agents API is currently in beta. Endpoints, request/response formats, and behavior may change as we iterate toward a stable release.
LibreChat exposes agents to external applications, scripts, and services through inference and event-delivery APIs.
Overview
The Agents API provides two inference interfaces, authenticated event delivery, and beta management routes:
- OpenAI-compatible Chat Completions —
POST /api/agents/v1/chat/completions - Open Responses API —
POST /api/agents/v1/responses - Agent Events —
POST /api/agents/v1/events - Agent Management —
/api/agents/v1/agents - Skill Management —
/api/agents/v1/skills
The inference interfaces support API-key authentication, optional OIDC authentication, and streaming responses. Agent Events use Remote Agents API-key authentication so LibreChat can bind each delivery to a stable source identity. Management routes instead use a deployment allowlist that binds an OIDC machine client to one existing LibreChat user and tenant.
LibreChat is adopting Open Responses as its primary API framework for serving agents. While the Chat Completions endpoint provides backward compatibility with existing OpenAI-compatible tooling, the Open Responses endpoint represents the future direction.
Enabling the Agents API
The Agents API is gated behind the remoteAgents interface configuration. All permissions default to false.
interface:
remoteAgents:
use: true
create: trueSee Interface Configuration — remoteAgents for all available options.
Note: Admin users have all remote agent permissions enabled by default.
OpenAPI Specification and Interactive Docs
LibreChat can serve the public Agents API specification at /api/openapi.json and interactive Swagger UI documentation at /api/docs. Both routes are disabled by default. Enable them with the top-level openapi setting:
openapi:
enabled: trueThe specification covers the public inference, event, Agent management, and Skill management routes described on this page. Keep the routes disabled unless your deployment intends to expose API documentation.
API Key Management
Once remoteAgents.use and remoteAgents.create are enabled, users can generate API keys from the LibreChat UI. These keys authenticate requests to the Agents API.
Authentication
The Agents API supports two authentication methods that can be used independently or together.
API Key
API key authentication is enabled by default. Generate API keys from the LibreChat UI once remoteAgents.use and remoteAgents.create are enabled.
Authorization: Bearer <YOUR_API_KEY>OIDC Bearer Token
For machine-to-machine scenarios where your infrastructure already has an OIDC provider, you can authenticate directly with OIDC Bearer tokens without a LibreChat API key.
Configure OIDC auth in librechat.yaml:
endpoints:
agents:
remoteApi:
auth:
apiKey:
enabled: false
oidc:
enabled: true
issuer: https://auth.example.com/realms/myrealm
# jwksUri is optional and auto-discovered from issuer if omitted
audience: my-client-idThen call the API with your OIDC access token:
curl -X POST https://your-librechat-instance/api/agents/v1/responses \
-H "Authorization: Bearer YOUR_OIDC_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "agent_abc123", "input": "Hello!"}'The OIDC token must belong to a user that already exists in LibreChat. Matching uses the
sub claim first, then falls back to email, preferred_username, or upn.
See Agents Endpoint - remoteApi for all configuration options.
Agent Events require an API key
OIDC-only authentication is not supported for the Agent Events endpoints. Use a Remote Agents API key when creating bindings, enqueueing events, and polling delivery status.
Agent Management API
The beta Agent Management API lets a service manage Agents and their attached resources without a browser session. It is independently authenticated from inference and Agent Events: only OIDC machine tokens configured under endpoints.agents.managementApi are accepted.
Each configured OAuth client is bound to one existing LibreChat userId and tenantId. After token verification, every request runs as that user and keeps the user's current role capabilities, Agent and Skill ACLs, provider restrictions, tool grants, file limits, and tenant isolation. A client binding does not make the user an administrator or grant access to resources the user cannot otherwise manage.
Agent Routes
| Method | Route | Purpose |
|---|---|---|
POST | /api/agents/v1/agents | Create an Agent |
GET | /api/agents/v1/agents | List accessible Agents |
GET | /api/agents/v1/agents/{id} | Read one accessible Agent |
PATCH | /api/agents/v1/agents/{id} | Update an Agent |
DELETE | /api/agents/v1/agents/{id} | Delete an Agent |
POST | /api/agents/v1/agents/{id}/files | Upload and attach one Agent resource file |
GET | /api/agents/v1/agents/{id}/files | List the Agent's accessible attached files |
DELETE | /api/agents/v1/agents/{id}/files/{fileId} | Remove an attached file from the Agent |
Agent create and update payloads use the same externally supported fields as the Agent Builder and reject unknown top-level fields. Create requires a model; update accepts only supplied fields. Responses expose the supported Agent configuration plus id, provider, nullable model, version, createdAt, and updatedAt, without persistence ownership fields.
Lists accept limit from 1 through 100, defaulting to 20, and an opaque cursor. When has_more is true, pass the returned after value as the next cursor; do not decode or construct cursors in clients.
curl https://your-librechat-instance/api/agents/v1/agents?limit=20 \
-H "Authorization: Bearer YOUR_MACHINE_ACCESS_TOKEN"curl -X POST https://your-librechat-instance/api/agents/v1/agents \
-H "Authorization: Bearer YOUR_MACHINE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Release assistant",
"provider": "openAI",
"model": "gpt-5.6",
"instructions": "Prepare concise release notes from verified changes."
}'File uploads use multipart/form-data with one file and a tool_resource value such as context, file_search, or execute_code. LibreChat applies the deployment capability, role grant, upload rate limit, per-file, file-count, and aggregate-size checks before attaching the resource. Removing a file requires edit access to the Agent and does not weaken the underlying file authorization rules.
Skill Routes
| Method | Route | Purpose |
|---|---|---|
GET | /api/agents/v1/skills | List accessible Skills |
GET | /api/agents/v1/skills/{id} | Read one accessible Skill |
PATCH | /api/agents/v1/skills/{id} | Update supported Skill metadata |
GET | /api/agents/v1/skills/{id}/files | List files in the Skill |
GET | /api/agents/v1/skills/{id}/files/{relativePath} | Read one Skill file |
PUT | /api/agents/v1/skills/{id}/files/{relativePath} | Create or replace one supported file |
Skill operations are limited to Skills visible to the bound user. Reads require Skill access, while metadata or file writes require the corresponding edit and Skill-authoring permissions. Paths are normalized beneath the Skill root; traversal, unsupported files, and oversized content are rejected.
Errors and Authentication
Management responses use structured errors with invalid_request, not_found, permission_denied, conflict, or internal_error codes. Resource authorization failures may be returned as not_found so callers cannot probe inaccessible IDs.
Machine tokens must be unexpired, match the configured issuer, identify one allowlisted client through azp or client_id, and satisfy the configured subject rule. By default, tokens must also match the configured audience. For providers such as Amazon Cognito that issue machine access tokens with client_id instead of aud, set tokenUse: access, omit audience, and require the expected OAuth scope with requiredScopes. Missing configuration or invalid credentials return 401; a bound account undergoing deletion returns 409. See managementApi.auth.oidc and managementApi.auth.clients for the complete claim and binding rules.
Endpoints
Chat Completions (OpenAI-compatible)
POST /api/agents/v1/chat/completionsUse any OpenAI-compatible SDK by pointing it at your LibreChat instance. The model parameter corresponds to an agent ID.
Example with curl:
curl -X POST https://your-librechat-instance/api/agents/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "agent_abc123",
"messages": [
{"role": "user", "content": "Hello, what can you help me with?"}
],
"stream": true
}'Example with OpenAI SDK (Python):
from openai import OpenAI
client = OpenAI(
base_url="https://your-librechat-instance/api/agents/v1",
api_key="YOUR_API_KEY"
)
response = client.chat.completions.create(
model="agent_abc123",
messages=[{"role": "user", "content": "Hello!"}],
stream=True
)
for chunk in response:
print(chunk.choices[0].delta.content, end="")List Models
GET /api/agents/v1/modelsReturns available agents as models. Useful for discovering which agents are accessible with your API key.
Open Responses API
POST /api/agents/v1/responsesThe Open Responses endpoint follows the Open Responses specification, an open inference standard initiated by OpenAI and built by the open-source AI community. It is designed for agentic workflows with native support for reasoning, tool use, structured outputs, and streaming semantic events.
curl -X POST https://your-librechat-instance/api/agents/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "agent_abc123",
"input": "What is the weather today?"
}'Caller-Executed Function Tools
The Open Responses endpoint accepts standard function tools supplied by the caller. LibreChat exposes these definitions to the model but does not execute them. When the model selects one, the response contains a function_call output item for the caller to execute.
To continue, send a new request whose input replays the returned function_call item followed by a matching function_call_output item. This handoff is stateless: it does not create a suspended run, and previous_response_id alone cannot replace the replayed tool exchange.
{
"model": "agent_abc123",
"input": [
{
"type": "function_call",
"call_id": "call_abc123",
"name": "lookup_order",
"arguments": "{\"order_id\":\"A-42\"}"
},
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\"status\":\"shipped\"}"
}
]
}Caller tool names may contain letters, numbers, underscores, and hyphens. Names must be unique and cannot replace a server-provided tool. A caller-executed tool must be the only tool selected in its turn; if the model mixes it with server-executed tools, LibreChat asks the model to retry the caller tool by itself.
For LibreChat-executed Agent tools, both headless inference endpoints enforce an enabled endpoints.agents.toolApproval policy, including deny, ask, and programmatic hooks. These calls have no interactive approval/resume channel: deny and ask block the tool instead of opening an approval prompt. Configure explicit allows only for tools the API client should be able to run unattended; when the policy is disabled, its approval hooks do not run. Caller-executed function tools remain the caller's responsibility.
Agent Events
Agent Events let an authenticated controller or source adapter deliver durable work to an Agent. Event delivery is a beta capability and its request, response, and runtime behavior may change.
The endpoints use the authenticated user, tenant, and API key; the target Agent must be visible to that user under the existing Remote Agents permissions. Agent Event requests also use the dedicated rateLimits.agentEvents bucket.
Deliver an Event
POST /api/agents/v1/events
Authorization: Bearer <REMOTE_AGENTS_API_KEY>
Idempotency-Key: webhook-42-resource-7
Content-Type: application/json
{
"mode": "fire",
"event": {
"id": "resource-7-ready-3",
"type": "resource.ready",
"occurredAt": 1786967999000,
"payload": { "resourceId": "resource-7" }
},
"target": { "agentId": "agent_abc123" },
"input": "Resource resource-7 is ready. Inspect it and report the result.",
"orderingKey": "resource-7"
}Send exactly one Idempotency-Key header and reuse it when retrying the same source-event-to-target delivery. The key must contain 1-256 letters, numbers, or the characters ._~:/+=-. Reusing a key with different delivery content returns a conflict.
The caller supplies the event id, type, occurredAt, and sanitized payload. LibreChat replaces any caller-supplied event.source with the authenticated API key identity and derives the user, tenant, request ID, and receive time. Do not place credentials or transport secrets in event payloads because accepted deliveries are persisted.
orderingKey is optional. Use a stable value when deliveries from different sources must remain ordered for the same resource.
A successful request returns 202 Accepted, an opaque delivery id, its current status, and a Location header. Poll that location:
GET /api/agents/v1/events/{delivery_id}
Authorization: Bearer <SAME_REMOTE_AGENTS_API_KEY>The delivery can be pending, leased, succeeded, or dead. The status response includes attempts and timestamps plus a result or public error when settled; it does not expose the stored payload, ordering key, retry history, or worker identity. Status access is scoped to the same user, tenant, and API key source.
For a bound continue, succeeded means the Agent turn was admitted, not that the requested work finished. Its status therefore also exposes a durable handling lifecycle: started, followed by exactly one of applied, completed_no_action, failed, or cancelled.
Action-aware sources can include an expectedAction with a tool name and optional argument subset. LibreChat reports applied only when that exact generation finishes with host-observed tool evidence matching the contract; model-authored prose is never accepted as proof. fire, steer, and unbound continue deliveries reject expectedAction.
Successful fire results include the conversation and generation identity that a later steer event can target.
Event-Driven Child Agents
An external system can bind a source actor to a direct child Agent, then continue that same child conversation across events. Bound child continuations are automatic after the API-key identity, binding ownership, parent relationship, and Agent authorization checks succeed; there is no separate feature toggle.
Register the actor with the same API key that will deliver its later turns:
POST /api/agents/v1/events/bindings
Authorization: Bearer <REMOTE_AGENTS_API_KEY>
Idempotency-Key: championship-7-player-hanae
Content-Type: application/json
{
"actorId": "hanae-kobayashi",
"parentConversationId": "director-conversation-id",
"parentMessageId": "director-message-id",
"target": { "agentId": "agent_hanae" }
}actorId can contain up to 128 characters. The parent must be an ordinary Agent conversation, and the target must be configured as one of that Agent's direct Subagents or an allowed self-spawn. A new binding returns 201; an idempotent replay returns 200. Both responses include id, actorId, agentId, and threadId.
Send later turns with the returned binding ID:
POST /api/agents/v1/events
Authorization: Bearer <SAME_REMOTE_AGENTS_API_KEY>
Idempotency-Key: game-12-ply-17-hanae
Content-Type: application/json
{
"mode": "continue",
"bindingId": "evtbind_...",
"event": {
"id": "game-12-ply-17",
"type": "chess.turn.ready",
"occurredAt": 1786968000000,
"payload": { "gameId": "game-12", "expectedPly": 17 }
},
"input": "Your clock is running. Read the position and submit one legal move.",
"expectedAction": {
"tool": "submit_move",
"arguments": { "gameId": "game-12" }
}
}LibreChat resolves the child Agent, thread, latest branch leaf, and ordering lane from the binding immediately before dispatch. Caller-supplied target and ordering fields cannot redirect a bound continuation. The request's Idempotency-Key becomes the stable public identity for that child turn across delivery retries, generation leasing, persisted messages, live activity, and a later HITL resume.
Each binding has an automatic durable mailbox. Its next event remains queued until the current turn reaches applied, completed_no_action, failed, or cancelled; different bindings stay independent and can run in parallel. Checkpoint continuation is attempted only for a compatible initialized turn. If a checkpoint is missing or cannot be restored, LibreChat falls back to durable message history without weakening receipt, authorization, or expected-action checks.
A bound actor can pause for Ask User or tool approval. LibreChat persists the exact signed suspension before exposing the pending action, and the binding's mailbox remains blocked until that same actor invocation resumes or settles. Event Actors require the durable MongoDB checkpointer; type: memory is not compatible. LibreChat negotiates generation protocol v2 and selects checkpoint or history continuation automatically. Existing protocol-v1 work remains on the durable-history path until it drains. See Generation Protocol Compatibility for mixed-version deployment requirements.
Coalescing Observational Events
Sources that can prove several bound continue events are interchangeable observations can give them the same source-defined coalesce.key:
{
"mode": "continue",
"bindingId": "evtbind_...",
"event": {
"id": "championship-7-game-12-move-18",
"type": "chess.move.completed",
"occurredAt": 1786968000750,
"payload": { "gameId": "game-12", "ply": 18 }
},
"input": "A tournament game advanced.",
"coalesce": { "key": "championship-commentary" }
}LibreChat collects compatible events for up to 750 ms, with at most 8 events and 512 KiB of combined envelopes. The child receives one deterministic batch document, but every source event keeps its own Idempotency-Key, delivery record, and receipt.
Use coalescing only for non-actionable observations. It is rejected for fire, steer, unbound continue, and deliveries with expectedAction; do not use it for commands, approvals, HITL requests, fences, or events whose individual timing matters.
In the authenticated parent conversation, each bound actor appears beneath its owning parent message. The Subagent panel can switch between actors and turns, load earlier activity, and expand a turn to show its full bounded activity. Event details include the type, source, occurrence time, and expected action. Visible run steps, tools, messages, and reasoning markers are included without raw reasoning text. The parent index returns at most 64 child threads and 20 recent tasks per child from a bounded source window, reports truncation instead of implying completeness, and caps the response at 96 KB. It is parent-, user-, and tenant-authorized; bindings, source key IDs, lease tokens, and worker state are not included in the projection.
The child thread remains hidden from normal conversation navigation and read-only to human chat routes, inherits the parent's temporary or expiration policy, and is limited to one direct-child level. A binding ID alone does not grant access; continuations are scoped to the user, tenant, and API key that created it.
Detached Event Actor Actions
Event Actor turns can detach eligible Actions and complete them durably. The delivery remains in its handling lifecycle while the Action runs; durable terminal evidence resumes the original signed actor invocation, and only the resulting host-observed tool evidence can satisfy expectedAction. Replays and competing replicas cannot launch the same reserved Action twice. If LibreChat cannot determine whether an external side effect began, it quarantines the launch instead of retrying it blindly.
LibreChat enables this internal completion work automatically when the selected built-in generation store advertises support. The in-memory store runs launch, completion, and continuation in one process and cannot recover that work after the process exits. Redis generation streams add durable restart recovery and replica handoff. Capability-owned delivery and recovery records remain invisible to older claimers during a mixed-version drain; there is no operator-managed producer flag.
Token Usage Tracking
All Agents API inference requests track token usage against the user's balance when token spending is configured. Both streaming and non-streaming responses aggregate every billed primary-Agent and Subagent model call into the top-level totals. The response also includes identity-free primary and subagent token breakdowns. Cache and reasoning-token details are included where the provider reports them.
Roadmap
- Open Responses as primary interface — We plan to expand the Open Responses endpoint with full support for agentic loops, tool orchestration, and streaming semantic events.
- Anthropic Messages API — We may add support for the Anthropic Messages API format as an additional interface in the future.
Related Documentation
- Agents — Creating and configuring agents
- Subagents — Configuring direct child Agents
- Agents Endpoint Configuration — Event runtime and authentication settings
- Interface Configuration — remoteAgents — Access control settings
- Token Usage — Configuring token spending and balance
- Open Responses Specification — The open inference standard
How is this guide?