You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ba72da4
Browse filesBrowse the repository at this point in the historyBrowse files
fix(litellm): use underlying provider for metadata, drop eager serialization
Align the LiteLLM integration with .agents/skills/sdk-integrations/SKILL.md.
Audit against the SKILL surfaced four issues:
- **`metadata.provider` was the framework name.** SKILL §Completion-style
explicitly says LiteLLM must set `metadata.provider` to the underlying
provider (openai / cohere / openrouter / ...), not "litellm". Fixed by
routing every span through `_resolve_provider(model)` which calls
`litellm.get_llm_provider(model)`; falls back to `"litellm"` only if the
lookup fails. `@lru_cache(maxsize=256)` on the resolver so the hot path
doesn't re-dispatch through litellm's routing table per call.
- **Excess serialization.** Every non-streaming wrapper called
`_try_to_dict(response)` on the full pydantic response then indexed
into it — but `bt_json` already serializes at log time. Replaced with
direct attribute reads via a shared `_get_field(obj, key, default)`
helper that works on both dicts and SDK objects (openai / anthropic /
cohere had all been open-coding this). Streaming paths left intact.
- **Dead code.** `_is_litellm_patched` was only used by crewai until #587
moved crewai to the "wrapper never owns tokens" pattern; no remaining
callers anywhere. Removed the helper and its two subprocess tests.
- **Excessive comments.** Trimmed the huge `wrap_litellm` /
`_is_litellm_patched` docstrings and the "wrapt wrapper for litellm.X"
one-liner on every wrapper.
Also lifted the rerank output cap (`results[:100]`) into
`integrations/utils.RERANK_OUTPUT_MAX_RESULTS` and documented the
"rerank exception to no-silent-caps" rule in the SKILL — cohere carries
the same magic number and can adopt the shared constant in a follow-up.
## Test plan
- [x] Updated existing VCR-backed tests to assert the underlying
provider (`openai`, `cohere`, `openrouter`) instead of `"litellm"`.
No cassette re-recording (HTTP requests unchanged; span-shape
assertions only).
- [x] Added positive `metadata["provider"] == "openrouter"` assertion
to the existing OpenRouter cassette test as coverage for the new
resolver.
- [x] Dropped the two `_is_litellm_patched` subprocess tests alongside
the helper.
- [x] **No new mocks/fakes, no cassette re-recording.**
- [x] `ruff check` + `ruff format --check` on touched files — clean.
- [ ] Reviewer to run: `cd py && nox -s "test_litellm(latest)"` and
`cd py && nox -s "test_litellm(1.74.0)"` (author's box has a
broken Python 3.14 install).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .agents/skills/sdk-integrations/SKILL.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -165,6 +165,7 @@ The integration that directly owns the model/provider API response owns token ac
165
165
- Do not over-serialize. Braintrust serializes at send/log time. Integration tracing only needs readable Python dicts/lists/scalars and materialized attachments.
- Do not wrap `span.log(...)` / `span.set_attributes(...)` in broad try/except. Braintrust span methods are boundary-safe.
168
+
-**Rerank exception to "no silent caps":** rerank result lists can be huge and are noisy in the span UI; cap the `output` list at a fixed max (e.g. 100 entries) via a named constant. The cap is compact-span hygiene, not coverage bounding — the model already ranked everything.
0 commit comments