Skip to content

docs(proxy): describe /v1/decisions and /v1/systemone in Swagger UI - #45838

Merged
kerry-berri merged 3 commits into
mainfrom
litellm_decisions_swagger_docs
Oct 10, 2026
Merged

kerry-berri merged 3 commits into
mainfrom
litellm_decisions_swagger_docs

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Swagger UI showed /v1/decisions and /v1/systemone as bare operations
  • No description, no request body, empty 200 response, both formats looked the same

How it solves it:

  • Route summaries and docstrings explain the question types and link the docs
  • Request body schema with a filled-in example, inlined from the Pydantic models
  • Typed 200 responses, OpenAIDecisionResponse and DecisionsResponse
  • Lazy OpenAPI snapshot and dashboard schema.d.ts regenerated

User Flow

Before: a developer opening Swagger to learn the decision request format finds nothing to read

  1. They open http://localhost:4000/ and expand the decisions tag
  2. POST /v1/decisions is titled "Decisions", has no description, no request body and an empty 200 response
  3. POST /v1/systemone looks identical apart from the title, so they cannot tell the two formats apart

After: the same page documents both formats with examples they can send as is

  1. They open http://localhost:4000/ and expand the decisions tag
  2. POST /v1/decisions reads "Ask questions about an input (OpenAI Decisions format)" with the predicate, choice and score types and a docs link
  3. The request body shows model, input, questions and safety_identifier with an example request, and the 200 response shows the OpenAIDecisionResponse schema
  4. POST /v1/systemone does the same for model, state and named questions with noul, choice and score, returning DecisionsResponse

before /v1/decisions

after /v1/decisions

after /v1/systemone

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/unit/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Screenshots / Proof of Fix

Both proxies run the same config, two decision deployments (jev on systemone/, luna on openai/) and a master key, base on port 4001 and tip on port 4000. The Swagger screenshots above are from the same two proxies

Before (09558ba)

/v1/decisions and /v1/systemone in the OpenAPI document

  1. for r in /v1/decisions /v1/systemone; do curl -s localhost:4001/openapi.json | jq -c --arg r "$r" '.paths[$r].post | {summary, description, requestBody, response_schema: .responses["200"].content["application/json"].schema}'; done
  2. Output:
    {"summary":"Decisions","description":null,"requestBody":null,"response_schema":{}}
    {"summary":"Systemone","description":null,"requestBody":null,"response_schema":{}}
    

After (4819de3)

/v1/decisions and /v1/systemone in the OpenAPI document

  1. for r in /v1/decisions /v1/systemone; do curl -s localhost:4000/openapi.json | jq -c --arg r "$r" '.paths[$r].post | {summary, request_properties: (.requestBody.content["application/json"].schema.properties | keys), required: .requestBody.content["application/json"].schema.required, example_keys: (.requestBody.content["application/json"].example | keys), response_schema: .responses["200"].content["application/json"].schema}'; done
  2. Output:
    {"summary":"Ask questions about an input (OpenAI Decisions format)","request_properties":["input","model","questions","safety_identifier"],"required":["input","questions","model"],"example_keys":["input","model","questions"],"response_schema":{"$ref":"#/components/schemas/OpenAIDecisionResponse"}}
    {"summary":"Ask named questions about a state (System One format)","request_properties":["model","questions","state"],"required":["state","questions","model"],"example_keys":["model","questions","state"],"response_schema":{"$ref":"#/components/schemas/DecisionsResponse"}}
    
  3. curl -s localhost:4000/openapi.json | jq -c '.paths["/v1/decisions"].post.description'
  4. Output:
    "Judge an `input` against 1 to 128 `questions` and get the answers back in the same order.\n\nQuestion types are `predicate` (yes/no with `probability`), `choice` (one of the `choices`, with\n`probabilities`) and `score` (an index into `levels`, with `probabilities`). Requests that break these\nrules are rejected with a 400 before any provider is called. `model` is any decision model in the proxy\nmodel list. System One decision models accept this format too, LiteLLM translates the request and the\nanswers. Streaming is not supported.\n\n[Docs](https://docs.litellm.ai/docs/decisions)"
    

Type

📖 Documentation

Caveats (if any)

Low

  • Request schemas are inlined per operation rather than referenced from components, so the snapshot grows by about 26 KB

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Link to Devin session: https://app.devin.ai/sessions/6fb807b73569493f85e18ebd83dfbf6f
Open in Devin Desktop: https://app.devin.ai/desktop/session/6fb807b73569493f85e18ebd83dfbf6f?variant=devin
Requested by: @kerry-berri


Note

Devin errored when opening this Pull Request as kerry-berri.
As a fallback, Devin opened this PR as itself.

Add summaries, descriptions, inlined request body schemas with examples and typed 200 responses to the
decision routes and their aliases, so the OpenAPI document and the lazy snapshot show both request formats

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


kerry seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Low impact] Adds OpenAPI documentation for decision endpoints.

The PR appears safe to merge, with a non-blocking correction needed to the safety_identifier description.

Findings

  1. P2 Dropping requires an explicit setting ▶

Summary

Adds Swagger descriptions, request examples, and typed responses for both decision formats and their unversioned aliases.

  • Swagger shows how to send both decision formats and what they return.

Reviews (1) · Last reviewed commit: "docs(proxy): describe /v1/decisions and ..." · Reviewed by Greptile

]
safety_identifier: Annotated[
str | None,
Field(description="A stable id for your end user. Sent to OpenAI and dropped for other providers"),

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.

P2 Dropping requires an explicit setting

The safety_identifier description says other providers drop it, but they reject it with a 400 unless drop_params is enabled. Developers following Swagger can add this field to an otherwise valid non-OpenAI request and get an unexpected error. State that dropping requires drop_params: true, then regenerate the snapshot and dashboard types.

@codspeed

codspeed Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

⚠️ 1 benchmark spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 31 untouched benchmarks


Comparing litellm_decisions_swagger_docs (b88ef62) with main (3981228)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (dc95de5) during the generation of this report, so 3981228 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@kerry-berri
kerry-berri enabled auto-merge (squash) October 10, 2026 19:18
@codecov

codecov Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.91667% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/proxy/common_utils/custom_openapi_spec.py 95.45% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@kerry-berri
kerry-berri merged commit bc2cc42 into main Oct 10, 2026
89 checks passed
@kerry-berri
kerry-berri deleted the litellm_decisions_swagger_docs branch October 10, 2026 21:05
DeoLeung pushed a commit to aiyou178/litellm that referenced this pull request Oct 11, 2026
…erriAI#45838)

* docs(proxy): describe /v1/decisions and /v1/systemone in Swagger UI

Add summaries, descriptions, inlined request body schemas with examples and typed 200 responses to the
decision routes and their aliases, so the OpenAPI document and the lazy snapshot show both request formats

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): cap _inlined schema walk depth for the recursion check

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit bc2cc42)
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.

3 participants