Skip to content

Conversation

@skamenan7
Copy link
Contributor

@skamenan7 skamenan7 commented Dec 11, 2025

Summary

This PR migrates the Agents API from the legacy @webmethod decorator pattern to the new FastAPI Router pattern, following the established Benchmarks API migration as a reference.

Changes

New Files

  • src/llama_stack_api/agents/__init__.py - Module exports with docstring
  • src/llama_stack_api/agents/api.py - Protocol definition
  • src/llama_stack_api/agents/models.py - Pydantic request models
  • src/llama_stack_api/agents/fastapi_routes.py - FastAPI router implementation

Modified Files

  • src/llama_stack_api/__init__.py - Export request models from main package
  • src/llama_stack/providers/inline/agents/meta_reference/agents.py - Updated to accept request model inputs
  • src/llama_stack/core/server/fastapi_router_registry.py - Register agents router

Key Implementation Details

  1. Request Models: All 5 API operations now use Pydantic request models:

    • CreateResponseRequest
    • RetrieveResponseRequest
    • ListResponsesRequest
    • ListResponseInputItemsRequest
    • DeleteResponseRequest
  2. OpenAPI Spec: Properly documents POST /v1/responses with:

    • Status code 200 (not 204)
    • Both application/json and text/event-stream content types
    • Correct schema references

Testing

Test case: Create Response (Non-Streaming)

Request:

POST /v1/responses
{
  "model": "ollama/llama3.2:3b-instruct-fp16",
  "input": "Tell me a one-liner joke.",
  "stream": false
}

Response (200 OK):

{
  "id": "resp_ef4879f3-f12d-421a-84ac-d461c68e2767",
  "object": "response",
  "status": "completed",
  "output": [{
    "type": "message",
    "role": "assistant",
    "content": [{
      "type": "output_text",
      "text": "A man walked into a library and asked the librarian..."
    }]
  }],
  "usage": {"input_tokens": 33, "output_tokens": 54, "total_tokens": 87}
}
Test case: Create Response (Streaming)

Request:

POST /v1/responses
{
  "model": "ollama/llama3.2:3b-instruct-fp16",
  "input": "Count 1 to 3.",
  "stream": true
}

Response (SSE Stream):

data: {"type":"response.created",...}
data: {"type":"response.output_text.delta","delta":"1"}
data: {"type":"response.output_text.delta","delta":", "}
data: {"type":"response.output_text.delta","delta":"2"}
data: {"type":"response.output_text.delta","delta":", "}
data: {"type":"response.output_text.delta","delta":"3"}
data: {"type":"response.completed",...}
Test case: Tool Calling

Request:

POST /v1/responses
{
  "model": "ollama/llama3.2:3b-instruct-fp16",
  "input": "What is the weather in San Francisco?",
  "tools": [{
    "type": "function",
    "name": "get_weather",
    "parameters": {"type": "object", "properties": {"location": {"type": "string"}}}
  }]
}

Response (200 OK):

{
  "output": [{
    "type": "function_call",
    "name": "get_weather",
    "arguments": "{\"location\":\"San Francisco\"}"
  }]
}
Test case: Get Response

Request:

GET /v1/responses/resp_ef4879f3-f12d-421a-84ac-d461c68e2767

Response (200 OK):

{
  "id": "resp_ef4879f3-f12d-421a-84ac-d461c68e2767",
  "object": "response",
  "status": "completed",
  "output": [{
    "type": "message",
    "role": "assistant",
    "content": [{"type": "output_text", "text": "A man walked into a library..."}]
  }]
}
Test case: List Responses

Request:

GET /v1/responses

Response (200 OK):

{
  "data": [
    {"id": "resp_1cd72689-49f8-465e-9e3c-ac06ee3b3386", "object": "response", ...},
    {"id": "resp_dfe88aaa-9550-48e3-a4f4-dc189c78dc7c", "object": "response", ...},
    {"id": "resp_ef4879f3-f12d-421a-84ac-d461c68e2767", "object": "response", ...}
  ],
  "has_more": false,
  "object": "list"
}
Test case: List Input Items

Request:

GET /v1/responses/resp_ef4879f3-f12d-421a-84ac-d461c68e2767/input_items

Response (200 OK):

{
  "data": [{
    "type": "message",
    "role": "user",
    "content": [{"type": "input_text", "text": "Tell me a one-liner joke."}]
  }],
  "object": "list"
}
Test case: Delete Response

Request:

DELETE /v1/responses/resp_ef4879f3-f12d-421a-84ac-d461c68e2767

Response (200 OK):

{
  "id": "resp_ef4879f3-f12d-421a-84ac-d461c68e2767",
  "object": "response",
  "deleted": true
}

Verify deletion (GET returns 400):

{
  detail: Response with id resp_ef4879f3-f12d-421a-84ac-d461c68e2767 not found
}

Related Issue

Closes #4336

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Meta Open Source bot. label Dec 11, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 11, 2025

✱ Stainless preview builds

This PR will update the llama-stack-client SDKs with the following commit message.

feat: Refactor Agents API to use FastAPI Router

Edit this comment to update it. It will appear in the SDK's changelogs.

llama-stack-client-node studio · code · diff

Your SDK built successfully.
generate ⚠️build ✅lint ✅test ✅

npm install https://pkg.stainless.com/s/llama-stack-client-node/0e4d34ff8c63e43ea6d773f1c5f82c92f0db162c/dist.tar.gz
llama-stack-client-kotlin studio · code · diff

Your SDK built successfully.
generate ⚠️lint ✅test ⏳

New diagnostics (2 note)
💡 Java/SchemaUnionDiscriminatorMissing: This union schema has more than one object variant, but no [`discriminator`](https://www.stainless.com/docs/reference/openapi-support#discriminator) property, so deserializing the union may be inefficient or ambiguous.
💡 Java/SchemaUnionDiscriminatorMissing: This union schema has more than one object variant, but no [`discriminator`](https://www.stainless.com/docs/reference/openapi-support#discriminator) property, so deserializing the union may be inefficient or ambiguous.
llama-stack-client-python studio · code · diff

generate ⚠️build ⏳lint ⏳test ⏳

llama-stack-client-go studio · code · diff

Your SDK built successfully.
generate ⚠️lint ❗test ❗

go get github.com/stainless-sdks/llama-stack-client-go@417fbac8e8bae354153a1905981d4f6a77a2db15
New diagnostics (3 note)
💡 Schema/EnumHasOneMember: This enum schema has just one member, so it could be defined using [`const`](https://json-schema.org/understanding-json-schema/reference/const).
💡 Go/SchemaUnionDiscriminatorMissing: This union schema has more than one object variant, but no [`discriminator`](https://www.stainless.com/docs/reference/openapi-support#discriminator) property, so deserializing the union may be inefficient or ambiguous.
💡 Go/SchemaUnionDiscriminatorMissing: This union schema has more than one object variant, but no [`discriminator`](https://www.stainless.com/docs/reference/openapi-support#discriminator) property, so deserializing the union may be inefficient or ambiguous.

⏳ These are partial results; builds are still running.


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
Last updated: 2025-12-23 22:15:16 UTC

@mergify
Copy link

mergify bot commented Dec 11, 2025

This pull request has merge conflicts that must be resolved before it can be merged. @skamenan7 please rebase it. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify bot added the needs-rebase label Dec 11, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 5efea81 to 3550616 Compare December 11, 2025 21:41
@mergify mergify bot removed the needs-rebase label Dec 11, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch 5 times, most recently from 36799de to 73a899e Compare December 15, 2025 14:17
@skamenan7 skamenan7 marked this pull request as ready for review December 15, 2025 15:42
@skamenan7
Copy link
Contributor Author

@leseb please take a look. thanks.

@leseb
Copy link
Collaborator

leseb commented Dec 16, 2025

@skamenan7 please resolve the conflicts

@mergify
Copy link

mergify bot commented Dec 16, 2025

This pull request has merge conflicts that must be resolved before it can be merged. @skamenan7 please rebase it. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify bot added the needs-rebase label Dec 16, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 73a899e to 0bd5296 Compare December 16, 2025 22:21
@mergify mergify bot removed the needs-rebase label Dec 16, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 7babe07 to cf2958d Compare December 16, 2025 22:34
@skamenan7 skamenan7 requested a review from leseb December 17, 2025 15:21
@leseb
Copy link
Collaborator

leseb commented Dec 17, 2025

@skamenan7 many failures in tests.

@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from cf2958d to 6fdaa15 Compare December 17, 2025 18:23
@mergify mergify bot removed the needs-rebase label Dec 17, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch 2 times, most recently from 814cb77 to 810fdad Compare December 19, 2025 14:03
@skamenan7 skamenan7 marked this pull request as draft December 19, 2025 18:40
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch 2 times, most recently from 4348bb0 to 0ceff95 Compare December 22, 2025 14:44
@mergify
Copy link

mergify bot commented Dec 22, 2025

This pull request has merge conflicts that must be resolved before it can be merged. @skamenan7 please rebase it. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify bot added the needs-rebase label Dec 22, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 1f48db1 to 6d599dc Compare December 22, 2025 20:35
@mergify mergify bot removed the needs-rebase label Dec 22, 2025
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch 6 times, most recently from f615d86 to 16620db Compare December 23, 2025 20:38
@skamenan7
Copy link
Contributor Author

skamenan7 commented Dec 23, 2025

I cleaned this PR up into 4 commits so it’s easy to review end-to-end.
Please review and provide feedback for any changes. Glad to fix or enhance. Thanks!

  1. feat: migrate Agents API to FastAPI router
    This is the core refactor: move the Agents API (including /v1/responses) off the legacy @webmethod path and onto the router registry pattern (mirroring how Benchmarks works). It introduces a dedicated agents/ package (api.py protocol, models.py request models, fastapi_routes.py router) and wires it into fastapi_router_registry.py.

  2. fix: support streaming responses from router endpoints in library client
    With the router migration, the streaming path for /v1/responses can surface as a FastAPI StreamingResponse (SSE) rather than the previous “async iterator” contract. The library client’s streaming logic was written around the old assumption and could end up iterating the wrong object or falling back into JSON serialization. This change makes the client explicitly handle both cases (AsyncIterator vs StreamingResponse.body_iterator) and consistently emit SSE as bytes.

  3. fix: disable OTEL SDK in docker integration tests
    CI docker integration runs were flaky due to OTEL exporters attempting to talk to an OTLP collector (and occasionally causing connection errors / shutdown noise). Telemetry integration is already disabled in tests (Replay tests delayed due to telemetry collector #4089), so for docker-mode I set OTEL_SDK_DISABLED=true to prevent exporter traffic during tests and keep the docker jobs deterministic.

  4. fix: dedupe responses input union in Stainless spec
    After the router migration, the OpenAPI request schema for POST /v1/responses shows up under CreateResponseRequest.input and ends up including a duplicated OpenAIResponseMessage-Input variant inside nested unions. Stainless codegen is sensitive to this and was failing with Go name clashes and Python duplicate declarations. I didn’t want to change the stable spec (oasdiff would treat that as breaking), so the fix is applied only to the combined/stainless spec generation: dedupe redundant sibling $ref entries during OpenAPI generation and regenerate the Stainless artifacts.

     cc: @leseb 
    

@skamenan7 skamenan7 requested a review from leseb December 23, 2025 22:02
@skamenan7 skamenan7 marked this pull request as ready for review December 23, 2025 22:02
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 16620db to 773d567 Compare December 23, 2025 22:04
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch 2 times, most recently from 98821bc to 1d39cfd Compare January 6, 2026 15:09
skamenan7 and others added 6 commits January 6, 2026 17:44
Move the Agents API surface to a router-based implementation and replace the
legacy single-file agents module with a package layout.

This includes wiring the Agents router into the router registry and updating
imports/tests accordingly.
Handle FastAPI StreamingResponse results for streaming endpoints so the library
client can iterate and forward SSE chunks correctly.
Telemetry collection is disabled in integration tests (llamastack#4089), but docker-mode
runs can still spin up OTEL exporters that attempt network connections and make
CI flaky. Disable the OTEL SDK in the container to avoid spurious failures.
When /v1/responses moved to the Agents router, the request body schema appears as
CreateResponseRequest.input and includes a duplicated OpenAIResponseMessage-Input
variant inside nested unions. Stainless codegen treats this as separate generated
types, causing Go name clashes and Python duplicate declarations.

Apply a combined-spec-only OpenAPI transform to drop redundant sibling $ref
entries and regenerate the Stainless artifacts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…raint

- Add # allow-direct-logging comment since llama_stack_api cannot
  import from llama_stack
- Remove ge=1 from max_tool_calls to preserve existing error message
  format expected by integration tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@skamenan7 skamenan7 force-pushed the feat/4336-agents-fastapi-router branch from 1d39cfd to b448c27 Compare January 6, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FastAPI Router Migration: Agents API

2 participants