OpenAI API Compatibility¶
LangGraph OpenAI Serve is an OpenAI-client compatibility layer, not a separate LangGraph-specific HTTP API. Public Responses, Chat Completions, and model behavior remain reachable through the configured OpenAI-compatible base URL.
The same contract lets LGOS run behind OpenAI-compatible intermediaries without a project-specific inference adapter. Generic gateway requirements are in the proxy guide; concrete Chainlit, Open WebUI, Files, LiteLLM, and Bifrost implementations belong to the Demo Stack.
Contract¶
- Registered graph names are exposed as OpenAI
modelvalues. - Core graph behavior must fit OpenAI-compatible request fields, Responses items, Chat objects, tool calls, streaming events, metadata, or error envelopes.
- Do not require custom payloads, headers, routes, or SSE event shapes for core behavior unless the OpenAI client path still works.
- Treat direct HTTP calls such as
curlas diagnostics; validate compatibility through OpenAI client behavior.
The implemented endpoints are listed in Reference.
Model Feature Discovery¶
The OpenAI Model object
has no metadata field. LGOS keeps its standard fields unchanged and places
feature discovery in a namespaced, versioned extension on model-list and
model-retrieval responses. Runtime-settings discovery remains detail-only:
{
"id": "simple-graph",
"object": "model",
"created": 1720000000,
"owned_by": "langgraph-openai-serve",
"lgos": {
"schema_version": 1,
"description": "Streams responses with configurable history and audience.",
"features": [],
"client_settings": {
"schema_version": 1,
"json_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"use_history": {
"type": "boolean",
"default": false
},
"audience": {
"type": "string",
"enum": ["general", "beginner", "expert"],
"default": "general"
}
},
"additionalProperties": false
},
"defaults": {
"use_history": false,
"audience": "general"
}
}
}
}
The standard OpenAI Model object has no description field. The required
GraphConfig.description is therefore exposed as
lgos.description on both list entries and detailed model
responses. It is API-owned presentation text; clients decide how to render it.
GraphConfig.features is the single source of truth: the runner uses it to
enable behavior, while model listing and retrieval serialize it for discovery.
GraphConfig.client_settings is an explicit, allowlisted public Pydantic model;
LGOS never publishes a graph's internal LangGraph context schema automatically.
Additive features do not require an outer schema-version change. The nested
runtime settings descriptor has its own version, and clients must ignore
versions they do not understand.
The two schema versions evolve independently. Adding an optional extension
field or a new feature value does not change version 1. Removing a field,
renaming it, or changing its type or semantics requires incrementing only the
affected schema version. Clients ignore unknown fields and feature values. An
unsupported outer version disables LGOS capability discovery; an unsupported
client_settings version disables only the settings UI.
| Feature | Enabled behavior |
|---|---|
client_events |
Streaming Responses may emit status commentary. Chat Completions ignores client events. |
file_inputs |
The graph accepts native file parts and resolves their opaque file_id values. |
interrupts |
The server supports the checkpointed interrupt/resume flow. |
GET /v1/models remains lightweight. Every entry contains the standard id,
object, created, and owned_by fields plus a small
lgos object with schema_version, description, and
features. Client-settings schemas remain detail-only.
Every successful LGOS GET /v1/models/{model} response includes the complete
lgos extension, even when its feature list is empty and it
has no client settings. A UI reads catalog descriptions from the list and
retrieves the selected model details through the same configured OpenAI client.
This keeps large schemas out of list responses and keeps internal or
secret-bearing runtime context out of discovery.
OpenAI treats added response properties as backward-compatible.
Direct JavaScript clients can read the property normally, and the
OpenAI Python SDK exposes it through model_extra.
An intermediary may rebuild a retrieved model from the standard fields and drop
extensions. For one LGOS deployment, a client can use one OpenAI base URL for
model listing, model retrieval, Responses, and Chat Completions; that URL may
be a proxy pass-through such as the demo's LiteLLM /v1/lgos-a catalog route. A
federating gateway may expose a normalized catalog for provider and model
routing, but that catalog is not necessarily a source of LGOS descriptions or
capabilities. Standard Responses requests do not depend on the extension. A UI
that offers graph-specific settings or capability controls must retrieve the
selected provider's detail object through a route that preserves it. Concrete
gateway configurations and native Responses requirements are documented under
OpenAI-Compatible Proxies.
Limited functionality signal
A missing description in model listing or missing or invalid
lgos metadata on model retrieval means the configured
endpoint is not preserving the optional LGOS discovery contract. A UI may
continue plain Responses text, but it must visibly label the model or chat
as Limited functionality and must not assume runtime settings, file
inputs, status commentary, or interrupts are available. A normalized
routing catalog cannot remove this requirement.
Runtime Settings¶
The request keeps each concern in its standard OpenAI location:
| Concern | OpenAI request location |
|---|---|
| System instructions | Responses instructions or an input system/developer message; a system message in Chat |
| Small graph-specific values | One metadata.lgos_settings string containing a JSON object |
| Graph selection | model |
| Caller-selected interrupt operation ID | Optional metadata.lgos_run_id UUID |
| Conversation correlation | Optional metadata.conversation_id string |
Only small graph-specific values belong to ClientSettings. A graph may expose
controlled semantic choices such as intended audience, but not arbitrary system
instruction text. Client-authored system instructions remain ordinary graph-input
messages.
OpenAI metadata permits at most 16 string pairs, with keys up to 64 characters
and values up to 512 characters. Public settings consume one pair; a
caller-selected interrupt run or conversation correlation value consumes
another. Clients use json.dumps() or JSON.stringify() to encode the complete
settings string and omit values equal to the advertised defaults. The
advertised JSON Schema describes the available settings; LGOS remains the
validation authority. The descriptor's separate defaults object is the
authoritative validated baseline; JSON Schema default keywords are annotations
and may precede Pydantic field normalization. Native OpenAI fields keep their
standard semantics. Graphs that need identity, authorization,
database clients, secrets, or other server-owned per-request context combine
client_settings with context_factory(request, settings).
LGOS reserves metadata keys beginning with lgos_; applications should use
their own names outside that prefix. The independent keys remain separate
rather than sharing one JSON envelope so each value retains OpenAI's full
512-character allowance. Arbitrary non-LGOS metadata continues through the
protocol-neutral graph request unchanged.
metadata.conversation_id is an optional, client-owned correlation value. It is
a documented metadata convention, not a server-managed conversation resource.
A client uses the same stable value for every Responses or Chat Completions request in
one conversation. LGOS maps it to the Langfuse-recognized
RunnableConfig.metadata.langfuse_session_id; each request remains a separate
trace, while Langfuse can group those traces in one
session. It does
not select checkpoint state or cause LGOS to retain conversation history; clients
still supply the input needed by each ordinary request. Omit the field when no
conversation exists; LGOS does not generate a fallback ID. Application graphs
may explicitly use it to scope their own stored data, but it is not authorization.
Clients targeting Langfuse should use an ASCII value shorter than 200
characters. The value is distinct from the OpenAI user field,
metadata.lgos_run_id, and per-request trace or request identifiers.
Per-Request Resolution¶
Every graph request starts from the registered defaults. Values supplied in
metadata.lgos_settings replace matching top-level defaults, and LGOS
validates the complete result. The merge is shallow: a supplied nested object
replaces that whole default value rather than recursively merging its keys.
Client settings are not persisted between requests. The paused Response ID and
interrupt call IDs identify durable state, but they do not restore runtime context.
Clients must resend non-default settings on every request that needs them,
including interrupt-resume requests. A later request that omits
lgos_settings uses registered defaults again.
When the required extension is missing or unsupported, the client omits runtime settings and shows the limited-functionality warning described above. See Configure LangGraph Runtime Settings for the complete author and client flow. Adapter support is summarized under demo client capability matrix.
Message And Schema Adaptation¶
Incoming OpenAI messages are converted to LangChain messages. The protocol
decoder also produces the small, protocol-neutral GraphRequest received by
GraphConfig adapters, keeping custom LangGraph schemas behind the public API
boundary. See
LangGraph Integration and
Custom Graphs.
Responses input_file.file_id content and native Chat Completions file parts
normalize to the same LangChain file content. LGOS does not expose Files routes
or own file storage. A client uploads through an external OpenAI-compatible
Files API and sends the returned file_id to a graph; the graph still owns file
interpretation. See Accept And Display Files.
Supported Responses Subset¶
POST /v1/responses implements stateless text, files, function calls, and
streaming over the same graph runner as Chat Completions. It intentionally does
not claim every field in the upstream OpenAI API.
| Request field or item | LGOS behavior |
|---|---|
model, input, instructions |
Supported. String input and ordered user, system, developer, and replayed assistant messages become LangChain messages. New instructions are rejected on interrupt resumes because a paused invocation cannot consume them. |
input_text |
Supported. |
input_file.file_id |
Supported and normalized to the existing graph file block. |
function tools, tool_choice, parallel_tool_calls |
Supported for client-owned functions. |
function_call and string-valued function_call_output |
Supported for ordinary client-tool continuation. Interrupt resumes accept only function_call_output items with previous_response_id. |
metadata, user |
Supported and passed through the protocol-neutral graph request boundary. They are not authentication. |
stream |
Supported with typed Responses SSE events. |
store |
Omitted and false mean false; true is rejected. |
text.format.type="text" |
Supported. |
tools=[{"type": "custom", "name": "lgos_..."}] |
LGOS hosted-tool selector; selected graph must declare each identifier. |
previous_response_id |
Supported for interruptible graphs to resume from an interrupted state. Rejected for non-interruptible graphs. |
conversation, background: true |
Rejected because LGOS has no Responses conversation store or background lifecycle. |
include, reasoning, generation controls, service tier, stream options, reusable prompts, prompt-cache fields, truncation |
Rejected rather than accepted without semantics. |
Unknown request fields also fail validation. Exact errors use the standard OpenAI envelope and identify the unsupported parameter where it is known.
Stateless Item Continuation¶
LGOS generates an opaque Response ID for correlation but does not persist it. There are no response retrieve, delete, cancel, compact, or input-item routes. Clients therefore keep an input ledger and resend the items needed by the next turn instead of using a server-side Conversation.
When continuing a function call, append every item from response.output
unchanged and then append a matching function_call_output. Replaying complete
SDK items preserves message and call IDs plus assistant phase. The current
SDK may serialize optional function-call caller and namespace fields as
null; LGOS accepts those null values but rejects non-null program or namespace
semantics. This state model follows OpenAI's documented manual item replay while
keeping storage in the client.
Each replayed function call requires one matching output. Missing, duplicate, or unmatched results fail validation before graph execution, including when the client requests streaming.
An interrupt continuation uses a narrower stateful path. The client sends the
paused Response ID as previous_response_id and sends only matching
function_call_output items. LGOS uses those opaque IDs to locate and validate
the paused checkpoint; it does not reconstruct ordinary conversation history.
OpenAI's previous-response chaining defines the client exchange, but does not execute or persist a LangGraph graph. LGOS remains responsible for checkpoint storage, complete-batch validation, and coordination across workers. The checkpointer owns paused execution state; the coordinator prevents overlapping runs. There is no separate interrupt-response store or Chat Completions resume codec.
LangGraph checkpoint and Store persistence are separate. A checkpointer keeps only paused workflow execution; a graph Store keeps explicit application data. Neither makes a Response ID retrievable or lets LGOS reconstruct a conversation.
Responses Output¶
| Graph result | Responses representation |
|---|---|
| Final assistant text | Completed message item with phase="final_answer" and output_text content |
| Visible streaming status | Separate completed message item with phase="commentary" |
| Client tool or interrupt | One function_call item per call |
| Tool result on the next request | Matching function_call_output item |
| URL citation | url_citation annotation on output_text |
| Provider-reported usage | usage on the completed Response |
Function arguments are complete JSON strings. The graph runner does not emit incremental arguments, so the Responses stream sends one argument delta before the corresponding done event. IDs and output indices remain stable throughout the typed event lifecycle.
On failure, the terminal response.failed object retains any partial answer
already streamed, with unfinished output items marked incomplete.
Streaming¶
Streaming responses use OpenAI-compatible Server-Sent Events. See LangGraph Integration for internal event handling and Request Cancellation for request-scoped disconnect cancellation, proxy behavior, and cooperative limits.
LGOS aggregates usage reported by LangChain model calls across the graph run.
Complete Responses include it in usage, and a Responses stream carries it on
the terminal response.completed object. Chat streams add the standard final
empty-choices usage chunk only when the request sets
stream_options={"include_usage": true}. When underlying providers report no
usage, LGOS omits it rather than estimating tokens.
Assistant Text Parity¶
The final rendered AIMessage.text is the canonical assistant text.
Non-streaming returns it directly. Streaming emits eligible message chunks
immediately and retains them until the final message arrives. It then
concatenates the chunks and compares them with the final text. If no text
streamed, LGOS emits the final text as a fallback; a mismatch instead produces
the protocol's failure sequence rather than a successful terminal event. This
check covers one graph run, not two independent LLM executions. Transient
status events are excluded.
When multiple streamable nodes contribute text, the graph's
output_to_message adapter must render their messages in the same order.
Streaming Status¶
The graph must declare GraphFeature.CLIENT_EVENTS before any public client
event can cross an HTTP route. Ordinary LangGraph custom data, malformed events,
debug values, and non-JSON Python objects stay private. Responses exposes only
validated status_event() values. Chat Completions ignores custom events.
Responses Commentary¶
A streaming Responses request needs no metadata opt-in. LGOS maps every visible
status description to its own completed assistant message with
phase="commentary" and maps the durable answer to a message with
phase="final_answer". A status whose graph-owned hidden flag is true is
suppressed. The custom namespace and done flag do not leak into the Response;
item completion is a wire lifecycle concept, not graph progress state.
Commentary is transient and streaming-only. Non-streaming execution calls the
graph once for its durable result and does not collect status history. The
OpenAI Python SDK's Response.output_text convenience property concatenates
text across both phases, so UIs must select final_answer messages for
the transcript and render commentary separately. The maintained Chainlit and
Open WebUI adapters do this. Other clients may ignore phase or show all text
as one answer; that is a client presentation limitation, not a reason to add a
custom server event.
Chat Completions vs Responses Boundary¶
Complex workflow features—such as streaming status commentary, checkpointed
persistence, and human-in-the-loop interrupts—are exclusively available through
the native Responses API (/v1/responses).
The Chat Completions API (/v1/chat/completions) provides strict, standard OpenAI
compatibility for simple graphs and tool calling. It streams plain text
delta.content chunks and ignores custom streaming events. Interrupt-enabled
models requested via Chat Completions fail fast with HTTP 400 Bad Request
indicating that interrupts require the Responses API.
| Graph result | Responses | Chat Completions |
|---|---|---|
| Assistant text | final_answer message |
delta.content |
| Interrupt requiring input | function_call item |
Unsupported (HTTP 400) |
| Citation | output_text.annotations |
message/final-delta annotations |
| Passive status | commentary message |
Ignored |
| Diagnostic progress or artifact | Ignored | Ignored |
| Midstream failure | error then response.failed |
OpenAI error object |
Status is deliberately not a tool call. In OpenAI function calling, a function call asks the client to execute work and return a result. A passive status describes backend work already in progress.
Citation Ownership¶
OpenAI url_citation annotations are the canonical citation contract. Their
URL, title, and text span associate a source with the answer. end_index is
inclusive, matching OpenAI's last-character convention.
Graphs attach LangChain citation annotations to their final AIMessage.
Responses returns them on output_text.annotations and emits
response.output_text.annotation.added during streaming. Chat Completions
returns them as message.annotations and as an extension on the final delta.
LGOS does not define a UI-specific source schema or reconstruct citations from
custom events.
Portable resource presentation belongs in the assistant text, not in the
annotation object. Graphs may return ordinary Markdown links and images in
message.content, including visible inline citation markers. Annotations do not
require clients to synthesize marker text. When a graph also emits structured
attribution, its url_citation remains limited to its standard URL, title, and
text span. Audio and video resources should use ordinary Markdown links rather
than UI-specific players. RAG graphs must preserve only resource URLs supplied
by their retrieved context and must not invent or rewrite them.
Structured citations remain available to OpenAI clients that need
machine-readable provenance. The citation-events demo showcases that optional
contract.
Only the Chat streaming field is a compatibility extension because the published Chat delta schema does not declare annotations. Responses annotations and their typed streaming event are standard fields.
See the official OpenAI citation contract.
Errors¶
OpenAI-compatible routes return errors in the OpenAI envelope:
{
"error": {
"message": "Graph 'missing' not found in registry.",
"type": "invalid_request_error",
"param": "model",
"code": null
}
}
Route code that knows the OpenAI error metadata should raise
OpenAIHTTPException with openai.types.shared.ErrorObject. Shared handlers
translate generic FastAPI validation and HTTP errors into the same envelope.
Invalid runtime settings return HTTP 400 with
param: "metadata.lgos_settings". A proxy-stripped model
extension does not make plain text generation invalid, but clients surface it
as limited functionality rather than silently presenting a fully capable
model.
Malformed interrupt inputs, a missing or duplicate tool result, and invalid
caller-supplied run UUIDs return HTTP 400. A structurally complete exchange that
does not match the durable pending set, or is stale or already completed,
returns HTTP 409 with code: "interrupt_state_conflict". A request that cannot
acquire its interrupt-run lease returns HTTP 409 with code: "run_busy".
Tool Calls And Interrupts¶
Tool definitions are accepted for OpenAI compatibility. Graphs can read their
normalized function definitions and choices from GraphRequest in
request_to_input or load tools independently, as the mock MCP demo does.
Responses accepts flat function tool definitions, named or automatic tool
choice, returned function_call items, and matching string-valued
function_call_output items. Chat supports the modern nested tools,
tool_choice, assistant tool_calls, and tool messages with matching
tool_call_id values. The deprecated Chat functions, singular
function_call, and function message role are rejected rather than silently
ignored.
Chat request fields outside the supported schema are rejected by
normal request validation, including generation controls such as temperature,
max_tokens, and n. Graphs own their model configuration; LGOS cannot apply
those fields to arbitrary workflows. Deprecated function fields have no separate parser
or migration path. An assistant message's function_call: null is accepted so
clients can replay SDK message objects unchanged.
Interrupt graphs require a client application that can collect and submit tool
results. Interrupts and checkpoint resumes are supported exclusively via
the Responses API (/v1/responses). Requesting an interrupt-enabled model via
Chat Completions returns HTTP 400 Bad Request.
Hosted Tools¶
Responses accepts LGOS hosted-tool selectors matching the OpenAI custom tool shape,
such as tools=[{"type": "custom", "name": "lgos_current_time"}]. Function schemas and
execution remain server-owned.
A graph declares its supported identifiers in GraphConfig.hosted_tools and
reads the selected identifiers from GraphRequest.hosted_tools. Identifiers
must match lgos_[a-z][a-z0-9_]*. Unknown or unavailable selectors return HTTP
400 with the offending tools.N.name parameter before execution or streaming.
The package validates selection; the graph binds and executes its own tools
using its native agent implementation. Internal calls do not become client-owned
function_call items. Responses echoes the selectors as standard CustomTool
objects in tools.
Responses accepts the selector directly in the standard tools parameter:
response = client.responses.create(
model="hosted-tool",
input="What time is it in Istanbul?",
tools=[{"type": "custom", "name": "lgos_current_time"}],
store=False,
)
Because custom is a standard OpenAI Responses tool type, proxies such as
Bifrost preserve this selection across normalized /openai/v1 routes as well
as passthrough routes. See the hosted-tool demo.
Files And display_file¶
Portable generated files use the standard Files API plus a client-owned
function. The client offers strict display_file arguments; the graph uploads
the bytes and returns their file_id; the trusted client backend downloads and
persists the file through its native UI; and the client appends a small matching
function_call_output. Neither file bytes nor a protected bearer URL are placed
in the transcript. There is no LGOS artifact field or custom chart event. See
Accept And Display Files.
Operation Identity¶
An initial interrupt request does not require metadata. LGOS generates a UUID
operation ID and embeds it in the paused Response ID. A caller may
instead supply a non-nil UUID in metadata.lgos_run_id; doing so lets it
retry an initial request deterministically if the response is lost. Reusing
that UUID while the run is pending re-emits the durable pending batch without
executing the interrupted nodes again. If the caller lets LGOS generate the UUID
and loses the first response, it has not learned an address for that pending
run; choose the UUID before sending whenever initial-response recovery matters.
Treat a caller-chosen UUID as single-use. LGOS deliberately deletes terminal checkpoint state and keeps no tombstone, so a later ordinary initial request with that UUID is indistinguishable from a new operation and can start again. Only resubmitting the old paused Response ID and call outputs is fail-closed after terminal deletion.
The public run UUID is not a UI chat ID. LGOS derives a fixed-length internal
checkpointer key from a server-trusted scope, the registered model, and the
operation, so two models or authenticated tenant scopes do not share state even
when callers use the same UUID. Configure the server scope from trusted request
or authentication state, never caller-controlled metadata or the OpenAI user
field. The default shared scope is appropriate only for a
single-tenant or shared-trust deployment. Conversation history remains
client-owned; the checkpoint contains only the isolated workflow state needed
while this operation is paused.
The authenticated scope must remain stable between the initial request and all resumes. A request resolved into another scope cannot address the pending checkpoint, even if it presents the same public run UUID and continuation IDs.
Interrupt Tool Envelope¶
Every pending LangGraph interrupt becomes an OpenAI function tool call named
lgos_interrupt. Its arguments string contains the JSON payload directly:
{
"question": "How should the refund be handled?",
"choices": ["approve", "reject"],
"allow_other": true
}
Response and call IDs are opaque. The Response ID locates the paused operation;
each call ID binds an interrupt to that Response and exact checkpoint generation.
Clients must persist and return both values unchanged. Mixing a Response ID with
another Response's calls returns HTTP 400 with param: "previous_response_id".
Retrying an initial request returns new Response and call IDs for the same pending
work; either complete exchange can resume it while that checkpoint remains current.
Resuming an Interrupt¶
Clients can resume using standard OpenAI previous_response_id:
{
"model": "interruptible",
"previous_response_id": "resp_lg_f654e9041bd84fd6a8bf53a49ca25699_0123456789abcdef0123456789abcdef",
"input": [
{
"type": "function_call_output",
"call_id": "call_lg_47ecb7c6f7b901230fc4d3119976daae11888d39c973953060b8a849c3d8a5f2_0123456789abcdef0123456789abcdef_6f719db6-1be2-4b8e-875c-c775f0f6c86a",
"output": "Verify the delivery address first."
}
],
"store": false
}
Each function_call_output.output is a string, following the standard
OpenAI function-output pattern.
LGOS passes it unchanged to LangGraph as the return value of interrupt().
Graphs that need structured answers own their JSON parsing and schema validation.
Parallel interrupts are one atomic interrupt batch: the resume request must answer all of them. A client must not select one call, mix ordinary function calls into that request, duplicate a result, or synthesize a call ID. Streaming clients persist the terminal Response ID and completed function-call items instead of reconstructing them from argument deltas.
Metadata is not required on a resume, but metadata.lgos_run_id, when
present, must match the operation encoded by previous_response_id.
The UI owns persistence of the paused Response ID and exact calls. It must store them before soliciting input so a reconnect can reproduce the same resume request. Persisting only rendered prompt text or only the user's response is insufficient.
Durable Validation And Recovery¶
For an interrupt-enabled run, LGOS uses LangGraph exit durability and holds a run-scoped coordinator lease while it reads state, validates a resume, and executes the graph. Same-key contention is rejected instead of queued. Exit durability stores state when the invocation pauses or finishes without retaining every intermediate superstep. LGOS drains the invocation before it exposes interrupt tool calls. It compares the submitted pending IDs and opaque state token with the durable checkpoint before passing answers to LangGraph. The displayed interrupt payload is not part of the resume input. Concurrent work for another operation remains independent; a second request for the same operation receives HTTP 409.
LGOS preserves checkpoint state only after it produces an interrupt batch for the client. It deletes the isolated thread after terminal completion and best-effort after failure or cancellation before a batch. Cleanup failure can leave an unreachable thread for operators to reap; it never replaces the original execution error. If the terminal HTTP response is lost, replaying the old resume returns a safe HTTP 409 and does not re-execute the completed operation. This is conflict detection, not durable storage of the terminal response; applications that need result replay must add a result/idempotency store at their own boundary.
An interrupted node restarts from its beginning when resumed. Any side effect
before interrupt() can therefore run again; make it idempotent or move it
after the interrupt. This is a LangGraph execution rule, documented in the
official interrupt guidance.
Moving work after interrupt() avoids replaying it when the node restarts, but
it does not make an external side effect exactly once: a process can still fail
after the effect succeeds and before its task result is durably recorded. Put
external effects in durable tasks and give the downstream operation an
idempotency key when duplicates are unacceptable; LangGraph's
idempotency guidance
describes that remaining crash window. The coordinator prevents overlapping
run execution, not crash-time exactly-once delivery.
Pending runs abandoned by users remain checkpoint data. Production operators must define an expiry policy that accounts for the maximum response window and deletes expired checkpoint threads through the checkpointer; do not treat ordinary database backups or retention as an active-run cleanup policy. See LangGraph's persistence documentation for the underlying checkpoint model.
Known Differences From OpenAI¶
modelselects a registered LangGraph graph, not an OpenAI-hosted model.- Responses implements the explicit subset above; response storage,
Conversations, general previous-response chaining, background work,
OpenAI-hosted tools, structured output, and unconsumed generation controls are
rejected.
previous_response_idis reserved for interrupt continuation. - Chat Completions remains a direct compatibility surface, while maintained demo UIs use Responses for every graph.
- The package exposes model listing/retrieval and health, but no Files storage; deploy a separate OpenAI-compatible Files service when graphs use file IDs.
- Authentication is not enforced by default.
- Token usage is present only when underlying LangChain model calls report it. LGOS aggregates reported usage across the graph run and never estimates missing counts.