Skip to content

Prototype header-based durable agent entrypoint - #480

Draft
shivam5 wants to merge 5 commits into
databricks:mainfrom
shivam5:poc/durable-header-entrypoint-interface
Draft

Prototype header-based durable agent entrypoint#480
shivam5 wants to merge 5 commits into
databricks:mainfrom
shivam5:poc/durable-header-entrypoint-interface

Conversation

@shivam5

@shivam5 shivam5 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What did you change, and why?

This is a draft interface prototype for preserving an application's existing JSON request body while adding durable execution metadata through HTTP headers. It is an alternative to the wrapped JSON contract in #476 and the explicit server in #477.

Developer contract

app = DatabricksDurableApp()

@app.entrypoint
async def agent(payload, context): ...

@app.on_resume
async def resume_agent(payload, context): ...

The client keeps its existing /invocations body. It supplies small execution metadata separately:

POST /invocations
Idempotency-Key: approval-1
Databricks-Agent-Session-Id: approval-session-1
Databricks-Background: true
Databricks-Stream: true

{"action":"publish the release notes","decision":"approve","wait_seconds":60}

The server validates and persists the original body plus normalized session metadata. It constructs context.run_id, context.session_id, context.attempt, context.is_recovery, and context.emit() for the agent. After a crash there are no request headers to replay; the server reconstructs context from the durable run record.

Durable CUJ in the cookbook

  • A background streamed proposal completes with requires_action.
  • The client polls the persisted result and submits approval as a second run with the same session header.
  • OpenAI Agents SDK state is stored under context.session_id.
  • SDK events are persisted through context.emit() and replayed with cursors.
  • The approved run includes a 60-second tool call so the process can be stopped and recovered through @app.on_resume.
Capability Result
Existing JSON request body Preserved
Foreground response body Preserved
Background execution Supported through headers
Pod/process recovery Supported
Durable stream replay Supported through context.emit()
HITL Two durable runs sharing one session
Final result Stored in the durable run row

How do you know it works?

  • 29 focused runtime/store/app tests pass.
  • Tests cover header-to-context mapping, unchanged foreground response bodies, recovery callback selection, and background stream submission.
  • Ruff check and format pass for source, tests, and cookbook files.
  • Cookbook modules compile successfully.
  • The OpenAI adapter imports successfully against openai-agents==0.19.4; no live model call was made.

Background and streaming client contract

Concern Contract in this POC
Background The existing body is unchanged. Headers select background mode; the app stores status/result and the client polls GET /invocations/{run_id}.
Streaming The developer calls context.emit(). Databricks-Stream: true returns SSE; reconnect uses ?after=<event-id>.
OpenAI/custom client The route and body can remain unchanged; the client adds durability headers plus polling/replay logic.
LangGraph SDK client Headers alone cannot preserve LangGraph's multi-route threads/runs protocol. Without an adapter, the client changes to the generic invocation route and passes thread_id in the session header.

The cookbook README includes concrete OpenAI Agents SDK and LangGraph before/after client snippets for background=true, stream=true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant