Adding OpenAI Agents SDK adapter#149
Conversation
|
I have read the CLA Document and I hereby sign the CLA |
|
@amitkojha05 you need to resolve conflicts |
|
|
||
| async def _normalize_input_item( | ||
| item: Any, | ||
| normalizer: BinaryNormalizer, |
There was a problem hiding this comment.
If not used in thie iteration, drop the parameter
There was a problem hiding this comment.
Done — dropped the parameter from _normalize_input_item
| cached = await self._cache.llm.check(params) | ||
| if cached.hit: | ||
| output = _rebuild_output(cached.content_blocks, cached.response) | ||
| return _cache_hit_model_response(output, _make_usage(0, 0)) |
There was a problem hiding this comment.
pass real cached tokens into _make_usage instead of (0, 0).
There was a problem hiding this comment.
Fixed — added input_tokens and output_tokens to LlmCacheResult, populated from the stored entry in llm_cache.py. Cache hits now call _make_usage(cached.input_tokens, cached.output_tokens) instead of (0, 0)
| # This is safe when one CachedModel wraps a single Agent whose tools | ||
| # don't change between calls — the typical usage pattern. | ||
| params = await prepare_params( | ||
| system_instructions, input, model_name, model_settings, self._opts, |
There was a problem hiding this comment.
Tool context omitted from cache key
Medium Severity
tools, handoffs, and output_schema affect get_response() behavior but are excluded from params. Shared CachedModelProvider usage can therefore replay tool calls or structured outputs from another agent configuration.
Reviewed by Cursor Bugbot for commit be73f0f. Configure here.
There was a problem hiding this comment.
Intentional design — documented in the inline comment above. Safe when one CachedModel wraps a single Agent with fixed tools, which is the typical usage pattern. Including tools in the cache key is deferred to a follow-up PR.
| ) -> LlmCacheParams: | ||
| """Convert OpenAI Agents SDK get_response() args to canonical ``LlmCacheParams``.""" | ||
| _ = opts | ||
|
|
There was a problem hiding this comment.
Prepare options do nothing
Low Severity
prepare_params discards opts, leaving OpenAIAgentsPrepareOptions.normalizer and wrapper opts arguments with no effect. This creates a public option that cannot influence binary or multimodal normalization despite mirroring the peer adapter API.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit ceedb6b. Configure here.
There was a problem hiding this comment.
opts is retained for API consistency with peer adapters. The normalizer field will be wired into _normalize_input_item when binary/multimodal dispatch is added — documented in the inline comment.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 4 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 842c541. Configure here.
| role="assistant", | ||
| content=text_parts, | ||
| ), | ||
| ) |
There was a problem hiding this comment.
Missing nested try/except in message rebuild fallback
Medium Severity
The except TypeError handler for ResponseOutputMessage.model_construct at line 307–315 calls model_construct again without a nested try/except, unlike the text_part helper (lines 248–251) which correctly wraps the retry in its own try/except Exception. In Python, if the retry inside except TypeError raises a different exception, the sibling except Exception on line 316 does not catch it — it only catches exceptions from the original try block. This means a failed retry would propagate as an unhandled exception, crashing the cache-hit path instead of falling back to SimpleNamespace.
Reviewed by Cursor Bugbot for commit 842c541. Configure here.
| params, | ||
| store_blocks, | ||
| LlmStoreOptions(tokens={"input": inp, "output": out_tok}), | ||
| ) |
There was a problem hiding this comment.
Cache store failure discards valid LLM response
High Severity
After a successful LLM call, _extract_blocks and store_multipart run without any error handling. store_multipart raises ValkeyCommandError if Valkey is unreachable, and the valid response is never returned to the caller. A transient cache infrastructure failure (Valkey down, network blip) would crash the entire agent workflow even though the LLM already produced a valid result. A caching layer's store path needs to fail gracefully so it doesn't block the primary operation.
Reviewed by Cursor Bugbot for commit 842c541. Configure here.


Summary
Adds
betterdb_agent_cache.adapters.openai_agents— cache adapter for the OpenAI Agents SDK (openai-agents).This is distinct from the existing
openai.py(Chat Completions) andopenai_responses.py(Responses API) adapters. The Agents SDK wraps those behind its ownModelabstract class withget_response()/stream_response(), andRunnerorchestrates multi-turn agent loops with handoffs and guardrails on top. This adapter intercepts at theModel.get_response()level — so agent workloads that replay the same tool-call sequences (evaluation, testing, multi-agentorchestration) skip the API entirely.
Changes
New:
betterdb_agent_cache/adapters/openai_agents.pyprepare_params()— normalizes Agents SDKget_response()inputs (system_instructions + Responses API input items) toLlmCacheParamsCachedModel(model, cache)— wraps any Agents SDKModel, interceptsget_response()for cache-before-call.stream_response()delegated directly (streaming not cached — BetterDB convention)CachedModelProvider(provider, cache)— wraps anyModelProviderso everyModelit returns is cache-enabled. Recommended integration viaRunConfig(model_provider=...)_normalize_input_item(item, normalizer)extracted as private helper matching the_normalize_user_content/_normalize_blockpattern from peer adapters_rebuild_output()gracefully handles OpenAI SDK Pydantic models when available, falls back toSimpleNamespacefor older stacksNew:
tests/adapters/test_openai_agents.py— 9 tests coveringprepare_paramsnormalization (string input, list input, settings),CachedModel(miss+store text, miss+store tool calls, hit, different prompts, error propagation, streaming delegation),CachedModelProviderNew:
examples/openai_agents/— runnable example (text agent + tools agent) with READMEModified:
pyproject.toml— addedopenai_agentsoptional extra,openai-agents>=0.0.14todevandall,openai-agentsto keywordsNo changes to
proprietary/. No changes topackages/agent-cache/(TypeScript).Design decisions
prepare_paramstakes(system_instructions, input, model_name, model_settings)as separate args because the SDK separates them inget_response()— same rationale as the Pydantic AI adaptertools,handoffs,output_schemaexcluded from cache key — safe when oneCachedModelwraps a singleAgent(documented inline)_normalize_input_itemdocstring; follow-up can add normalizer dispatchChecklist
Test note: 9 tests cover all paths including tool call round-trips and SDK version compatibility.
ruff checkclean,pytestgreen.Note
Medium Risk
Introduces a new caching integration at the Agents SDK
Model.get_response()layer and changes the LLM cache hit return shape to include stored token counts, which could affect any callers relying on priorLlmCacheResultfields or token/cost accounting.Overview
Adds an OpenAI Agents SDK adapter (
adapters/openai_agents.py) that wraps an Agents SDKModel/ModelProviderto cacheget_response()results (including tool-call outputs) while explicitly not cachingstream_response().Extends LLM cache hit results to return stored
input_tokens/output_tokens(persisted in cache entries) so adapters can reconstruct usage on cache hits, and adds tests plus a runnableexamples/openai_agentsdemo;pyproject.tomlgains anopenai_agentsextra and dev/all deps foropenai-agents.Reviewed by Cursor Bugbot for commit 842c541. Bugbot is set up for automated code reviews on this repo. Configure here.