Skip to content

feat(integrations-py): forward FastAPI route kwargs from the endpoint helpers - #2645

Merged
BenTaylorDev merged 1 commit into
mainfrom
ben1/fastapi-endpoint-route-kwargs
Sep 4, 2026
Merged

feat(integrations-py): forward FastAPI route kwargs from the endpoint helpers#2645
BenTaylorDev merged 1 commit into
mainfrom
ben1/fastapi-endpoint-route-kwargs

Conversation

@BenTaylorDev

@BenTaylorDev BenTaylorDev commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Closes #2644. Reported downstream as CopilotKit/CopilotKit#1270 (Jan 2025, second reporter Jun 2025); the duplicate-operationId half was reported separately as CopilotKit/CopilotKit#2672 and closed with a codegen workaround.

Problem

Every Python endpoint helper except add_strands_fastapi_endpoint registered its agent route with a bare decorator:

@app.post(path)
async def langgraph_agent_endpoint(input_data: RunAgentInput, request: Request):

An application that mounts an agent route inside an existing API could not set:

  • operation_id — FastAPI derives it from the handler name and path, so it is unstable and two agent routes in one app collide. OpenAPI client generators break on it.
  • dependencies — the app's own auth or rate-limit dependency could not be attached. The only workaround was global middleware, which then also covers routes that must stay open.
  • include_in_schema — the agent route could not be hidden from a public /docs.
  • name — no app.url_path_for(...) reverse lookup.
  • tags, summary, description — no grouping in /docs, and an API governance lint gate that requires a tag on every operation could not pass.

Change

Each helper takes **kwargs: Any and forwards it to app.post for the agent route only:

Helper Package
add_langgraph_fastapi_endpoint ag-ui-langgraph
add_crewai_flow_fastapi_endpoint, add_crewai_crew_fastapi_endpoint ag-ui-crewai
add_adk_fastapi_endpoint, create_adk_app ag-ui-adk
add_agentspec_fastapi_endpoint ag-ui-agent-spec
add_claude_fastapi_endpoint ag-ui-claude-sdk
add_managed_agents_fastapi_endpoint ag-ui-claude-managed-agents
add_watsonx_fastapi_endpoint ag-ui-watsonx
add_langroid_fastapi_endpoint, create_langroid_app ag_ui_langroid

Also in this PR:

  • Every helper annotates app as FastAPI | APIRouter, which ag-ui-adk already did. Mounting on a router is how an existing app gives the agent route a prefix.
  • create_adk_app and create_langroid_app forward **kwargs to the helper they wrap.
  • add_langroid_fastapi_endpoint already accepted **kwargs and silently dropped them. They now reach the route.
  • ag-ui-strands is untouched: it already forwards route kwargs, and this PR follows its precedent.

Defaults are unchanged, so the change is additive for current callers.

Design note: the agent route only

Metadata is not copied onto the other routes a helper registers (<path>/health, <path>/capabilities, /agents/state), for two reasons:

  1. FastAPI requires a unique operation_id and name per operation. Copying them would recreate the duplicate-operationId bug this PR is meant to fix.
  2. A health probe usually has to stay reachable without the agent route's dependencies.

Both are asserted by tests, so the decision is pinned rather than implied.

Testing

New test module per package (tests/test_endpoint_route_kwargs.py), each covering: metadata on the agent route, include_in_schema, dependencies on the agent route only, registration on an APIRouter, an unchanged default registration, and — where a second route exists — that the health route keeps its own operationId and tags.

Every suite run locally from a clean worktree at origin/main (uv sync --frozen, then uv run pytest):

langgraph              791 passed, 733 subtests passed   (1 pre-existing failure, see below)
adk-middleware         943 passed, 8 skipped
crew-ai                884 passed, 3 skipped, 30 deselected
claude-managed-agents  147 passed
claude-agent-sdk       116 passed
agent-spec              54 passed
langroid                53 passed
watsonx                 41 passed

New tests only:

langgraph              6 passed      adk-middleware  5 passed
crew-ai                6 passed      langroid        6 passed
watsonx                6 passed      claude-agent-sdk 6 passed
claude-managed-agents  6 passed      agent-spec      5 passed

Mutation-checked, so the tests fail for the intended reason:

  • Reverting @app.post(path, **kwargs) to @app.post(path): langgraph 4 failed / 2 passed, adk 3 failed / 2 passed, langroid 4/2, watsonx 4/2, claude-agent-sdk 4/2, claude-managed-agents 4/2, agent-spec 4/1, crew-ai 5/1.
  • Copying the kwargs onto the health route as well (langgraph): 3 failed, including test_health_route_keeps_its_own_identity.
  • Dropping the **kwargs forwarding from create_adk_app: test_create_adk_app_forwards_route_kwargs failed.
  • Restoring each file: all green again.

Pre-existing failure, unrelated to this change: integrations/langgraph/python/examples/tests/test_deepagents_subagents_contract.py::test_deepagents_subagents_graph_imports_without_openai_key. Verified on a pristine origin/main checkout with this PR's files reverted — it fails there too.

🤖 Generated with Claude Code

CI coverage note

unit-python-sdk.yml has no job for integrations/agent-spec/python or integrations/claude-agent-sdk/python, so the test modules those two packages already carry — and the two added here — never run in CI. The runs above are the only verification for them. Worth a follow-up; I did not add the jobs in this PR.

… helpers

Every Python endpoint helper except add_strands_fastapi_endpoint registered
its agent route with a bare decorator, so an application embedding an agent
route in an existing API could not set the route's name, tags, summary,
operation_id, dependencies or include_in_schema. The derived operation_id in
particular is unstable and collides between two agent routes, which breaks
OpenAPI client generators.

Each helper now takes **kwargs and forwards it to app.post for the agent
route only. The health, capabilities and /agents/state routes keep their own
identity, because FastAPI requires a unique operation_id and name per
operation and a health probe usually has to stay reachable without the agent
route's dependencies. Every helper also accepts an APIRouter, which
ag-ui-adk already did, and create_adk_app / create_langroid_app forward
**kwargs to the helper they wrap. add_langroid_fastapi_endpoint already
accepted **kwargs and dropped them; they now reach the route.

Defaults are unchanged, so this is additive for current callers.

Reported downstream as CopilotKit/CopilotKit#1270, with the duplicate
operationId half reported separately as CopilotKit/CopilotKit#2672.

Closes #2644

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@BenTaylorDev
BenTaylorDev requested a review from a team as a code owner September 4, 2026 17:33
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Python Preview Packages

Version 0.0.0.dev1788543215 published to TestPyPI.

Warning: These packages are built from contributor code that may not yet have been vetted for correctness or security. Install at your own risk and do not use in production.

Install with uv

Add the TestPyPI index to your pyproject.toml:

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = true

Then install the packages you need:

# Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1788543215' --index testpypi

# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1788543215' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1788543215' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1788543215' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1788543215' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1788543215' --index testpypi

Install with pip

pip install \
  --index-url https://test.pypi.org/simple/ \
  --extra-index-url https://pypi.org/simple/ \
  ag-ui-protocol==0.0.0.dev1788543215

Use --extra-index-url https://pypi.org/simple/ so pip can resolve
transitive dependencies (pydantic, fastapi, etc.) from real PyPI.


Commit: e21405f

@pkg-pr-new

pkg-pr-new Bot commented Sep 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

@ag-ui/a2a-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a-middleware@2645

@ag-ui/a2ui-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-middleware@2645

@ag-ui/event-throttle-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/event-throttle-middleware@2645

@ag-ui/mcp-apps-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-apps-middleware@2645

@ag-ui/mcp-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-middleware@2645

@ag-ui/a2a

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a@2645

@ag-ui/adk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/adk@2645

@ag-ui/ag2

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/ag2@2645

@ag-ui/agno

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/agno@2645

@ag-ui/aws-strands

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/aws-strands@2645

@ag-ui/claude-agent-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-agent-sdk@2645

@ag-ui/claude-managed-agents

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-managed-agents@2645

@ag-ui/crewai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/crewai@2645

@ag-ui/langchain

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langchain@2645

@ag-ui/langgraph

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langgraph@2645

@ag-ui/llamaindex

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/llamaindex@2645

@ag-ui/mastra

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mastra@2645

@ag-ui/pydantic-ai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/pydantic-ai@2645

@ag-ui/vercel-ai-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/vercel-ai-sdk@2645

@ag-ui/watsonx

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/watsonx@2645

@ag-ui/a2ui-toolkit

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-toolkit@2645

create-ag-ui-app

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/create-ag-ui-app@2645

@ag-ui/client

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/client@2645

@ag-ui/core

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/core@2645

@ag-ui/encoder

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/encoder@2645

@ag-ui/proto

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/proto@2645

commit: 6718b38

@MikeRyanDev MikeRyanDev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursory review: no critical issues found.

@BenTaylorDev
BenTaylorDev merged commit 54c1558 into main Sep 4, 2026
55 checks passed
@BenTaylorDev
BenTaylorDev deleted the ben1/fastapi-endpoint-route-kwargs branch September 4, 2026 20:37
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.

[Feature]: FastAPI endpoint helpers cannot set route metadata (name, tags, operation_id, dependencies)

2 participants