Skip to content

feat(decisions): serve System One format at /v1/systemone and OpenAI format at /v1/decisions - #45184

Merged
mateo-berri merged 9 commits into
mainfrom
litellm_systemone_endpoint
Oct 8, 2026
Merged

mateo-berri merged 9 commits into
mainfrom
litellm_systemone_endpoint

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • /v1/decisions only spoke the System One format
  • OpenAI shipped a Decisions API with a different request and response shape
  • Clients written against OpenAI's API could not use the proxy

How it solves it:

  • System One format moves to /v1/systemone and /systemone
  • /v1/decisions and /decisions now take OpenAI's Decisions API format
  • OpenAI requests get translated into System One, run through the same pipeline, and translated back
  • Playground System One tab now calls /v1/systemone
  • OpenAI-format requests are capped at 128 questions, the System One limit, so a bigger request gets a 400 before any upstream call
  • A body that is not JSON gets a 400 instead of a 500 when the proxy runs without auth
  • OpenAI-format responses keep guardrail_information when the caller sets include_guardrail_response

Intentional product change: callers sending System One bodies to /v1/decisions must switch to /v1/systemone, since /v1/decisions now expects OpenAI's shape and returns 400 otherwise

User Flow

Before: a developer using OpenAI's Decisions API format gets a 400 from the proxy

  1. They send POST http://localhost:4000/v1/decisions with input and a questions list (predicate, choice, score)
  2. The proxy answers 400 Invalid Decisions request because it expects state and a questions map
  3. POST http://localhost:4000/v1/systemone returns 404 Not Found

After: the same OpenAI-format request returns OpenAI-format answers, and System One callers use their own route

  1. They send the same POST http://localhost:4000/v1/decisions body
  2. They get 200 with an answers list of typed predicate, choice and score answers plus OpenAI-style usage
  3. A System One client sends its usual body to POST http://localhost:4000/v1/systemone and gets the same answers map as before
  4. Both responses carry a non-zero x-litellm-response-cost header

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)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Proxy started with python litellm/proxy/proxy_cli.py --config decisions_config.yaml --port 4000, calling Perplexity for real

model_list:
  - model_name: decider
    litellm_params:
      model: perplexity/pplx-decider-v1-27b
      api_key: os.environ/PERPLEXITY_API_KEY

general_settings:
  master_key: os.environ/DECISIONS_PROOF_MASTER_KEY

systemone_body.json:

{
  "model": "decider",
  "state": "Customer wrote: I was charged twice for my order #4411 and want one of the charges refunded today.",
  "questions": {
    "is_refund_request": {"type": "noul", "instructions": "Is the customer asking for a refund?"},
    "urgency": {"type": "choice", "instructions": "How urgent is this?", "criteria": {"low": "can wait a week", "high": "needs action today"}},
    "frustration": {"type": "score", "instructions": "How frustrated is the customer?", "criteria": ["calm", "mildly annoyed", "angry"]}
  }
}

openai_body.json:

{
  "model": "decider",
  "input": [{"role": "user", "type": "message", "content": [{"type": "input_text", "text": "Customer wrote: I was charged twice for my order #4411 and want one of the charges refunded today."}]}],
  "questions": [
    {"type": "predicate", "name": "is_refund_request", "instructions": "Is the customer asking for a refund?"},
    {"type": "choice", "name": "needs_human", "instructions": "Should a human agent take over?", "choices": [{"value": true, "description": "billing dispute that needs a person"}, {"value": false}]},
    {"type": "score", "name": "frustration", "instructions": "How frustrated is the customer?", "levels": [{"label": "calm"}, {"label": "mildly annoyed"}, {"label": "angry", "description": "uses hostile language"}]}
  ]
}

Before (df23f11)

System One format at /v1/systemone

  1. curl -sS -i localhost:4000/v1/systemone -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @systemone_body.json
  2. Output:
HTTP/1.1 404 Not Found
{"detail":"Not Found"}

OpenAI format at /v1/decisions

  1. curl -sS -i localhost:4000/v1/decisions -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @openai_body.json
  2. Output:
HTTP/1.1 400 Bad Request
x-litellm-response-cost: 0
{"error":{"message":"litellm.BadRequestError: Invalid Decisions request: 2 validation errors for DecisionsRequestBody\nstate\n  Field required [type=missing, input_value={'model': 'decider', 'inp...s hostile language'}]}]}, input_type=dict]\n    For further information visit https://errors.pydantic.dev/2.13/v/missing\nquestions\n  Input should be a valid dictionary [type=dict_type, input_value=[{'type': 'predicate', 'n...es hostile language'}]}], input_type=list]\n    For further information visit https://errors.pydantic.dev/2.13/v/dict_type","type":"invalid_request_error","param":null,"code":"400"}}

After (77872f6)

System One format at /v1/systemone

  1. curl -sS -i localhost:4000/v1/systemone -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @systemone_body.json
  2. Output:
HTTP/1.1 200 OK
x-litellm-response-cost: 1.336e-05
{"model":"pplx-decider-v1-27b","answers":{"is_refund_request":{"type":"noul","noul":0.999578470044738},"urgency":{"type":"choice","choice":"high","confidence":0.9956760234989415,"probabilities":{"low":0.0021619882505292073,"high":0.9978380117494707}},"frustration":{"type":"score","score":0.6902205412172965,"confidence":0.4426092958331813,"legend":{"0":"calm","1":"mildly annoyed","2":"angry"},"probabilities":{"0":0.3406866307802912,"1":0.6284061972221208,"2":0.03090717199758787}}},"usage":{"input_tokens":334,"output_tokens":3}}

OpenAI format at /v1/decisions

  1. curl -sS -i localhost:4000/v1/decisions -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @openai_body.json
  2. Output:
HTTP/1.1 200 OK
x-litellm-response-cost: 1.3520000000000001e-05
{"model":"pplx-decider-v1-27b","answers":[{"type":"predicate","name":"is_refund_request","probability":0.999578470044738},{"type":"choice","name":"needs_human","choice":true,"probabilities":[{"value":true,"probability":0.9537056989243478},{"value":false,"probability":0.0462943010756523}],"confidence":0.9074113978486955},{"type":"score","name":"frustration","score":0.5402765434232424,"probabilities":[{"value":0,"label":"calm","probability":0.4628774338253685},{"value":1,"label":"mildly annoyed","probability":0.5339685889260208},{"value":2,"label":"angry","probability":0.0031539772486107467}],"confidence":0.30095288338903103}],"usage":{"input_tokens":338,"input_tokens_details":{"cached_tokens":0,"cache_write_tokens":0},"output_tokens":3,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":341}}

After, Jev direct from TypeSafe (77872f6)

Same proxy and request bodies with model set to jev, using this config so the calls go straight to TypeSafe's own API

model_list:
  - model_name: jev
    litellm_params:
      model: typesafe/jev-latest
      api_key: os.environ/TYPESAFE_API_KEY

general_settings:
  master_key: os.environ/DECISIONS_PROOF_MASTER_KEY

System One format at /v1/systemone

  1. curl -sS -i localhost:4000/v1/systemone -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @jev_systemone_body.json
  2. Output:
HTTP/1.1 200 OK
x-litellm-response-cost: 1.6422e-05
{"model":"jev-1.13.0","answers":{"is_refund_request":{"type":"noul","noul":0.99},"urgency":{"type":"choice","choice":"high","confidence":1.0,"probabilities":{"low":0.0,"high":1.0}},"frustration":{"type":"score","score":0.96,"confidence":0.88,"legend":{"0":"calm","1":"mildly annoyed","2":"angry"},"probabilities":{"0":0.06,"1":0.92,"2":0.02}}},"usage":{"input_tokens":391,"output_tokens":67}}

OpenAI format at /v1/decisions

  1. curl -sS -i localhost:4000/v1/decisions -H "Authorization: Bearer $LITELLM_MASTER_KEY" -H 'Content-Type: application/json' -d @jev_openai_body.json
  2. Output:
HTTP/1.1 200 OK
x-litellm-response-cost: 1.6422e-05
{"model":"jev-1.13.0","answers":[{"type":"predicate","name":"is_refund_request","probability":0.99},{"type":"choice","name":"needs_human","choice":true,"probabilities":[{"value":true,"probability":0.63},{"value":false,"probability":0.37}],"confidence":0.26},{"type":"score","name":"frustration","score":0.83,"probabilities":[{"value":0,"label":"calm","probability":0.17},{"value":1,"label":"mildly annoyed","probability":0.83},{"value":2,"label":"angry","probability":0.0}],"confidence":0.74}],"usage":{"input_tokens":391,"input_tokens_details":{"cached_tokens":0,"cache_write_tokens":0},"output_tokens":61,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":452}}

Type

New Feature

Caveats (if any)

Severe

  • System One bodies sent to /v1/decisions now get a 400
    • Clients on v1.106.0-dev.1 must move to /v1/systemone

Low

  • input_image parts return 400 since System One is text only
  • safety_identifier is accepted but not forwarded upstream
  • Missing or mismatched upstream answers come back as refusal answers
  • Response model is the upstream model name, same as /v1/systemone
  • A config pass-through mounted at /v1/decisions still takes precedence
  • Greptile's note that the route ownership tests check structure is left as is, since they mirror feat(decisions): add unified /v1/decisions endpoint for Jev-compatible providers #44236 and every route also has functional tests
  • Integration suites under tests/integration were not run locally because they need Postgres and Redis

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

Note

Medium Risk
Breaking route contract for /v1/decisions affects existing System One clients; translation and answer-mapping logic must stay correct for predicate/choice/score edge cases.

Overview
Splits decision APIs by wire format: System One (state + keyed questions) moves to /v1/systemone and /systemone, while /v1/decisions and /decisions now accept OpenAI’s Decisions shape (input, list questions, typed answers).

OpenAI requests are validated with new Pydantic types, translated to System One via openai_transformation (predicate→noul, choice/score mapping, text state from messages), run through the same adecisions proxy path, then mapped back to OpenAI answers (including refusal when upstream data is missing). include_guardrail_response is honored on the OpenAI response path. Invalid or non-JSON bodies return 400 before upstream calls; OpenAI question count is capped at 128.

Routing/auth/OpenAPI/allowlists and the playground System One tab are updated to the new paths. Breaking: clients sending System One JSON to /v1/decisions must switch to /v1/systemone.

Reviewed by Cursor Bugbot for commit f360214. Bugbot is set up for automated code reviews on this repo. Configure here.

…format at /v1/decisions

The System One request format moves to /v1/systemone and /systemone. /v1/decisions and
/decisions now accept the OpenAI Decisions API format, translate it into a System One
request, route it through the same pipeline, and translate the answers back.
@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Adds new decision endpoint format alongside existing one.

The PR appears safe to merge with the documented client migration

What we checked:

  • Frozen responses still return guardrail details: The shared helper creates a new model with model_copy. OpenAIDecisionResponse allows extra fields, so the helper can add guardrail_information without changing the frozen original

Summary

This PR separates the two request formats: System One uses /v1/systemone, while OpenAI-format clients use /v1/decisions. Both use the existing Decisions request pipeline

  • The latest changes preserve requested guardrail_information after converting the response to OpenAI format
  • The previous guardrail finding is fixed. No new actionable issues were found
  • mateo-berri explicitly accepts the route-breaking change: existing System One clients must switch routes
  • mateo-berri also documents intentional limits: images are rejected, safety_identifier is not forwarded, missing or mismatched answers become refusals, the upstream model name is returned, configured pass-through routes take precedence, and structural route tests remain unchanged

Reviews (5) · Last reviewed commit: "refactor(decisions): validate proxy requ..." · Reviewed by Greptile

Comment thread litellm/decisions/openai_transformation.py Outdated
Comment thread litellm/types/decisions.py Outdated
@codspeed

codspeed Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_systemone_endpoint (f360214) with main (03ba79d)

Open in CodSpeed

@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.91892% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/decisions/openai_transformation.py 95.12% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

mateo-berri added a commit that referenced this pull request Oct 7, 2026
… 3.10

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 29e7154 (litellm_systemone_endpoint).
mateo-berri added a commit that referenced this pull request Oct 7, 2026
… 3.10

Backport of the #45184 follow-up to stable/1.104.x.
Cherry-picked from 29e7154 (litellm_systemone_endpoint).
/v1/decisions accepted up to 200 questions, but the System One request it translates to takes at most 128, so 129 to 200 questions failed with an internal validation error. Both now share MAX_DECISION_QUESTIONS.
mateo-berri added a commit that referenced this pull request Oct 7, 2026
Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 7ef1329 (litellm_systemone_endpoint).
mateo-berri added a commit that referenced this pull request Oct 7, 2026
Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from b6bb885 (litellm_systemone_endpoint).
mateo-berri added a commit that referenced this pull request Oct 7, 2026
…on tests

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 77872f6 (litellm_systemone_endpoint).
mateo-berri added a commit that referenced this pull request Oct 7, 2026
Backport of the #45184 follow-up to stable/1.104.x.
Cherry-picked from 7ef1329 (litellm_systemone_endpoint).
mateo-berri added a commit that referenced this pull request Oct 7, 2026
Backport of the #45184 follow-up to stable/1.104.x.
Cherry-picked from b6bb885 (litellm_systemone_endpoint).
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review: non-JSON bodies now return 400, OpenAI questions are capped at 128, and integration tests use /v1/systemone

@mateo-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

@mateo-berri

Copy link
Copy Markdown
Contributor Author

Kerry's stack #45129 to #44969 lands the OpenAI schema through provider configs first. This PR then rebases onto it, keeping /v1/systemone and the Playground switch

…point

# Conflicts:
#	litellm/proxy/decisions_endpoints/endpoints.py
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

…point

# Conflicts:
#	litellm/types/decisions.py
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

Comment thread litellm/decisions/openai_transformation.py
@mateo-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot 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.

Stale Bugbot comment from a previous run.

@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit f360214. Configure here.

mateo-berri added a commit that referenced this pull request Oct 8, 2026
…ns when requested

Backport of the #45184 and #45214 guardrail fix.
Cherry-picked from 855f0bb (litellm_systemone_endpoint) as merged into #45214 at c19ada6 (litellm_openai_decisions_provider).
mateo-berri added a commit that referenced this pull request Oct 8, 2026
…ns when requested

Backport of the #45184 and #45214 guardrail fix.
Cherry-picked from 855f0bb (litellm_systemone_endpoint) as merged into #45214 at c19ada6 (litellm_openai_decisions_provider).
@mateo-berri
mateo-berri merged commit 8fc31b1 into main Oct 8, 2026
114 of 117 checks passed
@mateo-berri
mateo-berri deleted the litellm_systemone_endpoint branch October 8, 2026 04:41
mateo-berri added a commit that referenced this pull request Oct 8, 2026
…and the openai Decisions provider to rc/1.105.0 (#44236, #45184, #45214) (#45189)

* feat(decisions): add unified /v1/decisions endpoint for Jev-compatible providers (#44236)

Backport of #44236 to rc/1.105.0.
Cherry-picked from 8b1990b (main).

* feat(decisions): serve System One format at /v1/systemone and OpenAI format at /v1/decisions

Backport of #45184 to rc/1.105.0.
Cherry-picked from 3339469 (litellm_systemone_endpoint). The playground System One tab is not on this line, so its UI hunks are dropped.

* fix(decisions): import assert_never from typing_extensions for Python 3.10

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 29e7154 (litellm_systemone_endpoint).

* fix(decisions): cap OpenAI-format questions at the System One limit

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 7ef1329 (litellm_systemone_endpoint).

* fix(decisions): return 400 for bodies that are not JSON

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from b6bb885 (litellm_systemone_endpoint).

* test(decisions): send System One bodies to /v1/systemone in integration tests

Backport of the #45184 follow-up to rc/1.105.0.
Cherry-picked from 77872f6 (litellm_systemone_endpoint).

* feat(decisions): add OpenAI as a Decisions provider

System One requests to openai/ models are translated to OpenAI's Decisions shape on the way out and OpenAI's answers are translated back, so both /v1/systemone and /v1/decisions can route to gpt-6-luna.

(cherry picked from commit b94bbbc)

* refactor(decisions): move the OpenAI wire translation into llms/openai

(cherry picked from commit d209a85)

* feat(decisions): route both request formats through a shared decisions IR

System One and OpenAI-format bodies now convert to one internal representation, and each provider translates it to its own wire format. OpenAI deployments receive the caller's messages, images, names, typed choice values, level descriptions and safety_identifier unchanged. System One providers return a 400 for image input. Cached and cache-write tokens are priced on both response shapes, and provider response extras survive the round trip.

(cherry picked from commit 0dd207f)

* fix(decisions): keep provider fields inside System One answers

(cherry picked from commit 1348de8)

* fix(decisions): load on Python 3.10 and 3.11 and bill cached tokens once under custom pricing

Decisions IR dataclasses used a mappingproxy default, which is only hashable from Python 3.12, so import litellm failed on 3.10 and 3.11. Decisions usage now reaches cost_per_token as a Usage with prompt_tokens_details, so custom pricing no longer adds cached and cache-write tokens on top of input_tokens that already include them

(cherry picked from commit 39012f1)

* fix(decisions): honor litellm OpenAI key and base settings for the openai provider

OpenAI decisions now resolve the key from litellm.api_key, litellm.openai_key, then OPENAI_API_KEY, and the base from litellm.api_base, OPENAI_BASE_URL, then OPENAI_API_BASE, matching other OpenAI calls. Providers own their configured key and base lookup through the endpoint config.

(cherry picked from commit e465919)

* test(decisions): clear every OpenAI base setting in the proxy OpenAI deployment test

(cherry picked from commit a2951b3)

* fix(decisions): send OpenAI instructions for System One questions without them and reject single-option questions

(cherry picked from commit e4081f7)

* fix(decisions): return guardrail_information on OpenAI-format decisions when requested

Backport of the #45184 and #45214 guardrail fix.
Cherry-picked from 855f0bb (litellm_systemone_endpoint) as merged into #45214 at c19ada6 (litellm_openai_decisions_provider).

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
mateo-berri added a commit that referenced this pull request Oct 8, 2026
…ble_1_104_x

feat(decisions): backport /v1/systemone, OpenAI-format /v1/decisions and the OpenAI Decisions provider to stable/1.104.x for v1.104.2 (#44236, #45184, #45214)
doonga pushed a commit to greyrock-labs/home-ops that referenced this pull request Oct 8, 2026
…04.2) (#374)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.104.0` → `v1.104.2` |

---

### Release Notes

<details>
<summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary>

### [`v1.104.2`](https://github.com/BerriAI/litellm/releases/tag/v1.104.2)

[Compare Source](BerriAI/litellm@v1.104.1...v1.104.2)

#### Verify Docker Image Signature

All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53).

**Verify using the pinned commit hash (recommended):**

A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
  ghcr.io/berriai/litellm:v1.104.2
```

**Verify using the release tag (convenience):**

Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/v1.104.2/cosign.pub \
  ghcr.io/berriai/litellm:v1.104.2
```

Expected output:

```
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
```

***

#### What's Changed

- feat(decisions): backport /v1/systemone, OpenAI-format /v1/decisions and the OpenAI Decisions provider to stable/1.104.x for v1.104.2 ([#&#8203;44236](BerriAI/litellm#44236), [#&#8203;45184](BerriAI/litellm#45184), [#&#8203;45214](BerriAI/litellm#45214)) by [@&#8203;mateo-berri](https://github.com/mateo-berri) in [#&#8203;45190](BerriAI/litellm#45190)

**Full Changelog**: <BerriAI/litellm@v1.104.1...v1.104.2>

### [`v1.104.1`](https://github.com/BerriAI/litellm/releases/tag/v1.104.1)

[Compare Source](BerriAI/litellm@v1.104.0...v1.104.1)

#### Verify Docker Image Signature

All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53).

**Verify using the pinned commit hash (recommended):**

A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
  ghcr.io/berriai/litellm:v1.104.1
```

**Verify using the release tag (convenience):**

Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules:

```bash
cosign verify \
  --key https://raw.githubusercontent.com/BerriAI/litellm/v1.104.1/cosign.pub \
  ghcr.io/berriai/litellm:v1.104.1
```

Expected output:

```
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
```

***

#### What's Changed

- chore(release): refresh dependencies on stable/1.104.x and cut 1.104.1 by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;44777](BerriAI/litellm#44777)
- chore(docker): bump pgbouncer to 1.26.0 by [@&#8203;devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#&#8203;45012](BerriAI/litellm#45012)

**Full Changelog**: <BerriAI/litellm@v1.104.0...v1.104.1>

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/New_York)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzMuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjEzMy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/374
stvnksslr pushed a commit to stvnksslr/litellm that referenced this pull request Oct 8, 2026
…format at /v1/decisions

Backport of BerriAI#45184 to stable/1.104.x.
Cherry-picked from 3339469 (litellm_systemone_endpoint, BerriAI#45184 is not merged yet). The playground
System One tab and managed agent authorization are not on this line, so those hunks are dropped,
and the lazy-disabled precedence test is dropped as in the BerriAI#44236 pick.

This branch is waiting to be deployed

1 waiting deployment
e2e-changed — f360214b Waiting Oct 8, 2026 by mateo-berri via oauth #3755
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.

2 participants