Skip to main content
The pinned OpenAI Python SDK (upstream.json) defines the /v1 routes, fields and types. This page states what Core does where those types are silent, such as status codes, error fields, defaults and list bounds, and where Core behaves differently from the official service. The coverage ledger lists the differences and open gaps; Sessions, events and history, message content, Vaults, source Files and Skills and Environment files and Artifacts own the rules of their resources. “Beta routes” below are the routes under /v1/agents and /v1/vaults. “Files and Skills” are the routes under /v1/files and /v1/skills, which ignore OpenAI-Beta.

Requests

Paths and methods

Creating an Agent, Vault, Credential, Environment Template, Environment file or Session returns 201, also for a streamed Session creation. An empty update body on an Agent or Environment Template advances updated_at and changes nothing else; timestamps have one-second precision.

Headers

Beta routes require exactly one OpenAI-Beta header value, equal to agents=v1. A missing, different or repeated value returns 400 with type and code invalid_beta and the message “To access the Agents API, set the ‘OpenAI-Beta’ header to ‘agents=v1’.” This check runs before authentication. agents=v0 is rejected. Every Agents API response, including errors and event streams, carries:

Authentication

/v1 accepts only a Project API key as Authorization: Bearer <key>. All keys of one Project act as the same caller: they share its resources and its Session creation retries. Core resolves the key and its Project in the database on every request, with no credential cache and a five-second timeout. Revoking a key or archiving its Project takes effect on the next request. All keys of a Project act as subject service_account/project:<Project ID>. Projects and keys describes key management. The optional OpenAI-Organization and OpenAI-Project headers must, when sent, appear once and equal core and proj_<Project ID>; any other value rejects the key.

Request bodies

Every /v1 JSON route passes one body gate before route decoding, validation or lookup: Agent create and update, Vault create, Credential create and update, Environment Template create and update, Environment file create, Session create and update, and Session events. DELETE routes, multipart Files and Skills uploads and Skill update keep their own readers. Except for the 413 size error below, gate errors are 400 with type and code invalid_request_error and a null param. Member names match exactly. A case variant such as Metadata or a nested Role is an unknown member and gets the route’s unknown-member error before any write. Errors guarded by echotext.Allowed, such as unknown-member, enum, schema-root and cursor errors, repeat caller values only when they are at most 256 bytes of printable UTF-8. An unknown member that cannot be repeated gets a generic message and a null param. Metadata errors use their own validation and may repeat longer keys.

Resource identifiers

A malformed path identifier gets exactly the response of a well-formed missing one on that route, including when the body or query is also invalid. Missing, malformed and foreign resources are indistinguishable. Identifiers that are UUIDs also resolve when written in another spelling that Go’s UUID parser accepts, such as uppercase, braces or urn:uuid:.

Errors

Error types

Other 400 responses use type invalid_request_error. Validation failures with an official equivalent use code invalid_request_error and the observed param and message; other request errors keep Core’s local codes, such as invalid_request or unsupported_or_invalid_configuration.

Validation errors

Lists

Lists return object: "list", data, has_more, first_id and last_id; an empty page has null first and last IDs. order defaults to desc. Environment files page with their own page token and are not covered here.

Query parameters

The pinned Python SDK drops empty query values, so list(order="") sends no order and uses the default. after is trimmed of surrounding whitespace. Checks run in this order: repeated keys, then limit, then order; Vault and Credential status is checked first. These checks run before any resource lookup. Vault and Credential lists accept status as a scalar, as status[] entries, or both, and filter by their union. Both statuses are listed by default. Another value returns 400 invalid_request_error with a null param and “Failed to deserialize query string: status: data did not match any variant of untagged enum VaultStatusFilterParam”.

Page size

A limit that is not a decimal integer, including an empty value, returns 400 invalid_request_error, “Failed to deserialize query string: limit: invalid digit found in string” on Beta lists; outside Vault and Credential lists, a value above the signed 64-bit range returns “Failed to deserialize query string: limit: number too large to fit in target type”. A leading + is accepted when encoded as %2B; a leading - returns the invalid-digit error on Beta lists except Vaults and Credentials. Skills return invalid_request, “limit must be an integer between 0 and 100.”; Files return invalid_request with the Files range message.

Cursors

after names a resource of the same list, inside its already resolved parent and tenant. The parent is resolved first: a missing or foreign parent returns its 404 before the cursor is read. A cursor that does not resolve, whether random, malformed, of another type, of another parent, deleted or of another tenant, returns:

Agents

Saved configuration

Agent create requires model. Core saves and returns these values for omitted fields: Saving a value does not make it executable. Session creation admits a smaller set; see Session admission.

Configuration validation

Agent create and update bodies and the inline agent of Session create are checked against the pinned shapes of tools, text, reasoning, service_tier, multi_agent, model, name and instructions, before their parsers and before Harness admission. Failures return 400 with type and code invalid_request_error: Within one object Core reports a union’s type first, then unknown members, then member values in document order, then missing members; tools before text, and the whole object before the duplicate and schema-root checks. Schemas without a string root type are not checked. Function and output schemas, MCP transport, request_metadata, metadata and x_agents_core keep their own parsers. Update bodies and the inline Session agent are validated before the Agent lookup, so owned, foreign, missing and malformed Agent IDs give the same response. Core saves values the pinned shapes allow even when it cannot run them: function names of any length, enabled programmatic tool calling, reasoning effort max and service tier flex.

Session admission

A Session’s effective configuration must also pass execution admission, which applies to saved and inline configuration alike. Admission reports protocol errors from the table above first, including duplicate tools and schema roots in saved Agents, then these, all 400 unsupported_or_invalid_configuration before any write: A per-Session tools replacement admits a Session whose saved tools would be rejected. Support for each tool and Harness is in execution and tools. Omitted, null and explicit medium text verbosity give the same Session configuration. For a model whose native catalog declares no verbosity support, the Codex adapter drops a medium setting and uses the model’s default, and rejects low or high.

Update, delete and list

Sessions

Configuration snapshot

Session creation copies the effective Agent configuration into an immutable snapshot. With agent_id, the saved Agent is read once; fields in the inline agent replace the saved field whole, including arrays, and null tools clears the list. Omitted fields inherit; an inline x_agents_core that omits harness keeps the saved harness. Saved Agent metadata never becomes Session metadata. Later Agent updates or deletion affect only new Sessions. stream defaults to false. stream and agent_id cannot be null. Omitted or null metadata is {}. Creation validates the body and metadata types, the request fields and initial input, and the placement and streaming input requirements before looking up a creation retry. For new work, Core resolves the Template, saved Agent and model configuration, binds Vault Credentials, then validates the selected Harness and execution configuration before writing. A failed dependency lookup rechecks the retry identity so an already committed creation remains recoverable.

Creation retries

Send an Idempotency-Key of 1–128 bytes that is not only whitespace; a longer or whitespace-only key returns 400 invalid_request. An empty header counts as no key. Without a key, every request creates a new Session. The official service creates a new Session for each request even with the same key; Core returns the original one. Keys are scoped to the Project; any key of the Project, including one issued after a rotation, can retry. A request that has an inline Agent without model or names a saved Agent, a template, initial files or preparation, vault_ids or credential references, x_agents_core, or an openai_hosted environment is compared as sent, before any of those sources is read: a matching retry returns the original Session even after the Agent, template, Credential or deployment default changes or is deleted. Other requests are compared by their resolved configuration. Model provider keys enter the comparison only as fingerprints.

Update and list

POST /agents/sessions/{session_id} accepts only metadata, which is required: null or {} clears it and an object replaces all pairs. Execution state and the creation retry identity are unchanged. GET /agents/sessions accepts agent_id, which matches the Session’s immutable root Agent ID, including inline Agent IDs and Agents that were since updated or deleted. The filter applies before pagination; an empty agent_id is a filter, not an omission.

Delete

DELETE /agents/sessions/{session_id} deletes a Session that is idle or failed, has no queued, running or waiting root Turn and no pending input reservation. Subagent child Turns and pending Environment file writes do not block deletion. To delete running work, send agent.session.input.cancel, wait until the Session is idle, then delete. Input waiting for its Environment cannot be cancelled; the Session becomes deletable when the input starts, its five-minute deadline passes or the Environment fails. Core admits a Turn in the same transaction that returns 202 for its input, so a deletion right after that 202 returns 409.

Response fields

A Session’s agent.tools omits tool_search declarations, which the pinned Session tool union does not include; the frozen configuration keeps them. On self_hosted Sessions, environment.remote_url is Core’s daemon WebSocket URL, /api/v1/agent-daemon/ws under the public URL, which only OpenAgentCore’s Runtime daemon speaks; requests cannot set it. Other Session fields follow the pinned types; x_agents_core is described in the Agents API guide.