Add avp-openai-agent package for the OpenAI Agents SDK - #7
Open
Patrick Carney (pcarney8) wants to merge 6 commits into
Open
Add avp-openai-agent package for the OpenAI Agents SDK#7Patrick Carney (pcarney8) wants to merge 6 commits into
Patrick Carney (pcarney8) wants to merge 6 commits into
Conversation
New python/agents/avp-openai-agent/: subclasses agents.RunHooks and translates the SDK's lifecycle into AVP v0.1 events, mirroring avp-claude-agent for Anthropic. Maps on_llm_start/end → model_turn_*, on_tool_start/end → tool_*, on_handoff + on_agent_end → subagent_*, and reasoning items → reasoning_emitted. Ships a TracedOpenAIRunner for drop-in observability over an existing Runner.run call. Shared pricing gains OpenAI rows (gpt-5 family, gpt-4.1 family, o4-mini) plus an AVP_PRICES_PATH env override so ops can hot-swap a price table without a code release. Makefile real-LLM and examples gates loosened to accept either ANTHROPIC_API_KEY or OPENAI_API_KEY; each test/example self-skips on missing preflight. Verified: make test (324 tests), make conformance (20/20 cases, 22/22 events), real-LLM smoke (3/3 against gpt-5-nano), example 04 end-to-end against live gpt-5-nano. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
node_modules/ and package-lock.json are both gitignored for typescript/avp/, so a fresh checkout has neither and `make smoke` fails on `tsc: command not found`. Install on demand if the directory is missing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tests: five new files (+26 unit tests, +1 real-LLM) matching the
shape avp-claude-agent already has:
- test_local_tools_bridge: function_tool registry conversion
- test_provider_from_env: gen_ai.provider.name resolution rules
- test_agent_started_surface: tools/subagents/OTel attrs on
agent_started, plus the once-per-root invariant
- test_cost_source: avp.cost.source provenance (computed/unknown)
and wire spelling under the dotted alias
- test_subagent: handoff edge cases (sequential, frame parenting,
defensive no-ops, structured outputs)
- real-LLM: function-tool round-trip (retries once if the model
skips the tool, then fails)
Examples: rename 04 -> 08 so OpenAI examples group at the end
(01-07 Anthropic / Claude Code, 08-09 OpenAI). New 09 mirrors 07's
TracedOpenAIRunner / drop-in observability pattern.
Makefile: positional provider scoping. `make smoke anthropic`,
`make test-real-llm openai`, `make examples anthropic` all work;
provider word is parsed from MAKECMDGOALS, `anthropic` / `openai`
declared as no-op .PHONY targets so Make doesn't error on the bare
word, smoke uses $(MAKE) recursion to propagate PROVIDER through
sub-targets. Help text updated. Bare `make smoke` / etc. unchanged.
Verified: make test (350 tests pass, up from 324), make conformance
(20/20, 22/22), provider-scoped dry-runs route to the correct
package + example lists.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each provider now owns a decade: 01-09 Anthropic / Claude Code, 10-19 OpenAI. Leaves room for additional examples in either lane without renumbering. 08_openai_agents_audited -> 10_openai_agents_audited 09_openai_agents_traced_client -> 11_openai_agents_traced_client Updated docstring labels, the in-file `Run:` hint, and the Makefile EXAMPLES_OPENAI list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Before: ReasoningEmittedEvent fell through to the catchall, printing just the class name. In live trajectory output this produced a confusing layout — a bare "ReasoningEmittedEvent" line followed by the next event's content on the line below looked like one event with two unrelated parts. After: ReasoningEmittedEvent renders as either the truncated summary text or a "<redacted>" marker, matching the level of detail every other event already gets from format_event. Caught in example 11 output where gpt-5-nano produced a redacted reasoning item alongside a real text_emitted; the bare class-name fall-through made it look like the reasoning carried the answer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Without `reasoning.summary` set in ModelSettings, the OpenAI Responses API returns an empty `summary` on each ResponseReasoningItem — GPT-5 still reasons server-side (you still pay reasoning tokens) but the text isn't surfaced. The translator honestly emits `avp.reasoning.redacted=true`, which is correct but not what an audit demo should show. Set `Reasoning(summary="auto")` on each example's Agent so ReasoningEmittedEvent carries plaintext. Passthrough by design: SDK-level knobs stay at the SDK layer (your own Agent construction); Commission stays provider-neutral. Example 10 demonstrates this by passing a custom `agent_factory` to the translator rather than relying on the default-built Agent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
python/agents/avp-openai-agent/: subclassesagents.RunHooksand translates the OpenAI Agents SDK lifecycle into AVP v0.1 events. Mirrorsavp-claude-agentfor the OpenAI side. IncludesTracedOpenAIRunnerfor drop-in observability over an existingRunner.runcall, plus CLI (avp-openai-agent describe+ stdin/NDJSON).avp/data/prices.json(gpt-5 family, gpt-4.1 family, o4-mini), plusAVP_PRICES_PATHenv override so ops can hot-swap a price table without a code release (next-best-thing to a dynamic pricing API — neither OpenAI nor Anthropic publishes one).test-real-llmandexamplesgates loosened to accept eitherANTHROPIC_API_KEYorOPENAI_API_KEY; each test/example self-skips on missing preflight. New worked example04_openai_agents_audited.py.subagent_invoked/subagent_returnedpairs to keep the v0.1 wire frozen. Semantic stretch documented in the translator and README.Test plan
make test— 324 tests pass across all 5 packages (19 new inavp-openai-agent, 2 new inavppricing)make conformance— 20/20 cases pass, 22/22 event types coveredmake format-check && make lint— cleangpt-5-nano(~9.6s, well under $0.01)gpt-5-nano— converged, $0.0002, full lifecycle wire shape correctmake smoke(full paid matrix) — defer to reviewer / CIKnown follow-ups (separate PRs)
avp-openaiSDK adapter for the raw Responses API (parallelsavp-anthropic)avp-codex-agentfor the Codex CLI (no upstream Python SDK; subprocess + stream parsing)🤖 Generated with Claude Code