Compare commits

...

451 Commits

Author SHA1 Message Date
Kazuhiro Sera 751c6f60bd docs: updates for #3823 2026-07-13 16:39:08 +09:00
Kazuhiro Sera 8221e424db feat(realtime): track response usage in session context (#3812) 2026-07-13 07:42:49 +09:00
DongBo b24d5dd460 fix(handoffs): preserve user messages containing history wrappers (#3815) 2026-07-12 21:56:08 +00:00
Kazuhiro Sera 088075f4f5 chore: enable flake8-async for runtime source (#3813) 2026-07-13 06:48:13 +09:00
Dhruva Das beb3c5102f fix(models): raise UserError for conflicting provider args instead of assert (#3809) 2026-07-12 06:50:12 +00:00
Kazuhiro Sera 08859339ee docs: update translated pages 2026-07-11 10:24:43 +09:00
Kazuhiro Sera 5a9d221f0e docs: stabilize two examples 2026-07-11 10:18:18 +09:00
Kazuhiro Sera bcce208e61 docs: updates for hosted multi-agent support (#3789) 2026-07-11 10:09:01 +09:00
github-actions[bot] 41e79f1594 Release 0.18.2 (#3805)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-11 10:06:15 +09:00
seanturner83 6cf3600d4a fix(litellm): surface content-filter refusals instead of an empty turn (#3769) 2026-07-11 00:52:45 +00:00
Kazuhiro Sera e1f7c12515 fix: make conditional tools and web search examples deterministic 2026-07-11 09:38:53 +09:00
Kazuhiro Sera 75b928ea79 chore: enable RUF100 for runtime source 2026-07-11 09:01:08 +09:00
Kazuhiro Sera 0fce2cb187 chore: remove unused noqa directives (#3804) 2026-07-10 23:59:52 +00:00
Kazuhiro Sera 0a0b7be088 refactor: remove unused Responses include validator 2026-07-11 08:48:51 +09:00
Kazuhiro Sera 23c5276aa7 chore: enable RUF012 for runtime source (#3803) 2026-07-11 08:47:45 +09:00
Kazuhiro Sera aeed7bbcf8 chore: enable G004 logging lint rule (#3802) 2026-07-10 23:25:02 +00:00
Kazuhiro Sera fb8fb10599 docs: update AGENTS.md for git operations 2026-07-11 08:24:13 +09:00
Kazuhiro Sera 93317a87e6 refactor: share retry-after parsing (#3801) 2026-07-11 08:22:00 +09:00
Kazuhiro Sera eb54a61cc7 refactor: share retry error metadata extraction (#3800) 2026-07-11 07:58:13 +09:00
Kazuhiro Sera e354126180 refactor(sandbox): share Runloop rclone setup (#3799) 2026-07-10 22:49:28 +00:00
Kazuhiro Sera bc0dbb3ead refactor(sandbox): share E2B rclone setup (#3798) 2026-07-10 22:32:27 +00:00
Kazuhiro Sera 4c5d630c45 refactor(sandbox): share extension PTY output collection (#3797) 2026-07-11 07:26:41 +09:00
Kazuhiro Sera 77f7f9a7fb refactor(sandbox): share core PTY output collection (#3796) 2026-07-10 22:14:27 +00:00
Kazuhiro Sera fdca3ab389 chore(lint): enable RUF006 for runtime source 2026-07-11 07:05:06 +09:00
Otis Cui 322a3334cb fix: serialize model-backed rollout interruptions as dicts (#3790) 2026-07-11 07:02:05 +09:00
Kazuhiro Sera df2ddd41eb feat: support GPT-5.6 request controls (#3794) 2026-07-11 06:48:04 +09:00
Kazuhiro Sera 0354f482a8 feat: add hosted multi-agent beta support (#3788) 2026-07-10 17:46:43 +09:00
Kazuhiro Sera 2bd03971f9 chore: exempt OpenAI package from dependency cooldown (#3792) 2026-07-10 17:24:10 +09:00
Kazuhiro Sera dd0300bff9 fix(sandbox): own Unix PTY fd close tasks (#3780) 2026-07-10 13:46:31 +09:00
Kazuhiro Sera 32bf99dff3 fix(sandbox): own Docker deferred cleanup tasks (#3779) 2026-07-10 09:58:31 +09:00
Kazuhiro Sera 4e06694db2 fix(realtime): use monotonic playback timing (#3776) 2026-07-10 09:49:41 +09:00
Kazuhiro Sera 152baf182a fix(realtime): enqueue callback errors synchronously (#3777) 2026-07-10 09:49:24 +09:00
Kazuhiro Sera 89653d26f6 fix(sandbox): own Daytona PTY worker tasks (#3778) 2026-07-10 09:48:14 +09:00
github-actions[bot] 1760f73ba4 Release 0.18.1 (#3775)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-10 08:36:38 +09:00
Kazuhiro Sera 28026bcd01 docs: stabilize tool guardrail and web search examples 2026-07-10 08:24:36 +09:00
Kazuhiro Sera 574e2f74cd docs: update translated pages 2026-07-10 08:23:25 +09:00
Kazuhiro Sera 133208381c feat: add GPT-5.6 model defaults and migrate examples (#3774) 2026-07-10 07:58:22 +09:00
Kazuhiro Sera 8724b1b9ba fix: support cache-write usage across OpenAI Python versions (#3773) 2026-07-10 07:14:43 +09:00
Kazuhiro Sera 70c447e14f fix(realtime): make session cleanup deterministic (#3767) 2026-07-09 11:34:36 +00:00
Kazuhiro Sera 6bb69bc2d4 docs: update readme 2026-07-09 20:12:11 +09:00
WinkleMad 532acdf32c fix: send logprobs=True when top_logprobs is set on Chat Completions (#3763) 2026-07-09 07:54:18 +00:00
Anas Khan 1b0c7c2025 fix(models): accumulate streamed logprobs in place to avoid O(n^2) copies (#3762) 2026-07-09 14:38:31 +09:00
Anas Khan 5807751080 fix(sessions): handle list content in AdvancedSQLiteSession browsing helpers (#3761) 2026-07-09 14:18:47 +09:00
Cheemi 158b2f489e docs: clarify agent tool state options (#3754)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-08 23:26:45 +00:00
Kazuhiro Sera 60d3f95219 fix: preserve nested tool state during restoration (#3753)
Co-authored-by: Tao An <1250043+tao-hpu@users.noreply.github.com>
2026-07-08 15:44:19 +09:00
Kazuhiro Sera 163caa3aa8 docs: update README 2026-07-08 08:47:08 +09:00
Kazuhiro Sera 3063306db1 test(items): document refusal None invariant (#3751) 2026-07-08 08:29:40 +09:00
Anas Khan b10a7e9b50 docs(realtime): fix RealtimeRunner context docstring (#3748) 2026-07-07 23:24:44 +00:00
Minh Vu b3f8d8ce54 fix: close Chat Completions streams on early exit (#3689)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-08 08:19:37 +09:00
Kazuhiro Sera 078a28f11e docs: updates for v0.18.0 (#3741) 2026-07-07 15:05:03 +09:00
github-actions[bot] 668fabd6fe Release 0.18.0 (#3742)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-07 15:00:48 +09:00
Kazuhiro Sera 4fde807f1f feat: add Unicode storage option to SQLAlchemySession (#3746) 2026-07-07 03:38:02 +00:00
comp b4606c8f4c fix(visualization): keep fillcolor on handoff nodes by merging style attributes (#3744) 2026-07-07 03:26:38 +00:00
Kazuhiro Sera 909c5c434a feat: update default realtime model to gpt-realtime-2.1 (#3740) 2026-07-07 09:23:20 +09:00
Kazuhiro Sera 4a7dc08d31 docs: make hosted_mcp/on_approval.py stabler 2026-07-07 08:50:54 +09:00
Kazuhiro Sera 94c1f6095f docs: updates for v0.17.8 release (#3737) 2026-07-07 08:37:36 +09:00
github-actions[bot] 7a828f6db2 Release 0.17.8 (#3739) 2026-07-07 08:34:26 +09:00
Kazuhiro Sera 0ffb9e062c docs: update README.md 2026-07-06 15:41:39 +09:00
saime428 5d4a752c24 docs: add sandbox examples to examples index (#3731)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-07-06 06:36:42 +00:00
Kazuhiro Sera 3d07ff1687 feat: add invalid final output recovery handler (#3736) 2026-07-06 15:25:54 +09:00
Kazuhiro Sera 1643dbe617 chore: update runtime-behavior-probe skill to use request_user_input 2026-07-04 17:21:03 +09:00
Kazuhiro Sera e7f835b6c6 chore: update maintainer-review skill 2026-07-04 10:53:34 +09:00
Kazuhiro Sera 849241498f test: improve coverage for stream and sandbox edge cases (#3730) 2026-07-04 10:51:32 +09:00
Kazuhiro Sera ec8fbb875e docs: update translated pages 2026-07-04 09:43:51 +09:00
Kazuhiro Sera 70d01a9eca chore: improve error handling in code-change-verification 2026-07-04 09:04:52 +09:00
Kazuhiro Sera a898061dfa docs: make markdown style consistent across the project 2026-07-04 09:04:30 +09:00
Kazuhiro Sera 106ecb6bfe docs: update PR template and codex-change-verification skill 2026-07-04 08:50:59 +09:00
Kazuhiro Sera fe7d10625d docs: update translated pages 2026-07-04 08:47:25 +09:00
Danny 2afb6e1a24 docs: add DProvenanceKit to external tracing processors list (#3726) 2026-07-02 23:01:09 +00:00
Imran Hassanali 343c06fae1 fix(sandbox): length-frame exec-stdin writes so file I/O works over a… (#3719) 2026-07-03 07:55:52 +09:00
Om Borse 56921c89fc fix(handoffs): enforce strict Pydantic validation when strict_json_schema=True (#3724) 2026-07-02 15:42:43 +09:00
dependabot[bot] f13a3f78f1 chore(deps): bump actions/checkout from 6.0.2 to 7.0.0 (#3717) 2026-07-02 14:10:56 +09:00
dependabot[bot] 8d78731826 chore(deps): bump actions/stale from 10.2.0 to 10.3.0 (#3716) 2026-07-02 14:10:37 +09:00
dependabot[bot] ecfa2e0db6 chore(deps): bump actions/setup-python from 6.2.0 to 6.3.0 (#3715) 2026-07-02 14:10:23 +09:00
dependabot[bot] 829e19a7b7 chore(deps): bump astral-sh/setup-uv from 8.1.0 to 8.2.0 (#3714) 2026-07-02 14:10:07 +09:00
Anas Khan 655c805c92 fix(visualization): escape quotes and backslashes in DOT names (#3712) 2026-07-01 00:36:45 +00:00
Kazuhiro Sera 7713342bed chore: update maintainer-review skill 2026-06-30 15:11:31 +09:00
Anas Khan fea17ef542 fix(util): preserve non-dict Mapping values in _to_dump_compatible (#3700) 2026-06-29 02:33:41 +00:00
Kazuhiro Sera 97bc99101a chore: update PR template 2026-06-29 11:25:24 +09:00
Kazuhiro Sera 81fe6ab348 chore: adjust maintainer-review skill details 2026-06-26 08:31:34 +09:00
Minh Vu 8c688b96ac fix: redact realtime validation failure logs (#3687) 2026-06-26 08:28:17 +09:00
Minh Vu ab38ee5d45 fix: propagate realtime session iterator cancellation (#3686) 2026-06-26 08:19:49 +09:00
Kazuhiro Sera 3321967587 chore: adjust maintainer-review skill details 2026-06-26 07:39:09 +09:00
Kazuhiro Sera 92137d222b docs: improve hosted MCP tool example 2026-06-24 14:39:32 +09:00
github-actions[bot] 8a0e34caaa Release 0.17.7 (#3682) 2026-06-24 14:12:59 +09:00
MUHAMMAD SALMAN HUSSAIN 30ff4a5239 fix: recursively extract HTTP errors from nested ExceptionGroups (#3556) 2026-06-24 10:43:47 +09:00
Kazuhiro Sera 16d16ec2be chore: update maintainer-review skill to have two phases 2026-06-24 09:14:51 +09:00
Kazuhiro Sera f706d65124 chore: adjust examples-auto-run skill 2026-06-24 07:27:57 +09:00
Yaohao Wu 2df8adcae7 fix: add hint to duplicated MCP server tool name error message (#3678) 2026-06-23 05:59:52 +00:00
Kazuhiro Sera 7192bc968a docs: add SDK maintainer references and review guidance (#3676) 2026-06-23 11:20:57 +09:00
MAV a9b7b7ef4a fix(realtime): prevent ambiguous multi-agent tool dispatch (#3441) 2026-06-22 22:34:44 +00:00
shize li 28d2a6c838 feat: add buffered Chat Completions tool-call streaming (#3506) 2026-06-22 07:12:44 +00:00
Timothy Asiimwe 3f6324c2d2 docs: fix OpenAI capitalization in auto-generated ref titles (#3646) 2026-06-22 13:54:05 +09:00
ByteWise f115dd6015 fix: reduce sandbox sink buffering and spool timeouts (#3642) 2026-06-22 13:18:11 +09:00
安妮的心动录 e605bd20a2 feat: expose configurable websocket max_size limit (#3645) 2026-06-22 13:14:54 +09:00
Yufeng He 9168c387eb fix: report effective Blaxel timeouts (#3643) 2026-06-22 13:11:20 +09:00
Michal Chudy 593331a0a6 fix: #3620 avoid stale object-id dedupe in server conversation tracker (#3621) 2026-06-22 12:53:47 +09:00
Rohit Rastogi 0bd3d1b865 fix(e2b): wake PTY output collection on process exit (#3610) 2026-06-22 12:48:24 +09:00
vidigoat 7328f790be fix(items): empty list/tuple tool output dropped via all([]) == True (#3554) 2026-06-22 12:15:54 +09:00
Andy Freeland ce4cc62d86 fix: remove dependency on types-requests (#3509) 2026-06-22 12:08:43 +09:00
Matthew.K 50c8b74c50 fix: gate remote-mount edit guidance by mode (#3423) 2026-06-22 02:36:18 +00:00
Matthew.K 4ebf880953 fix: validate ls special permission bits by position (#3420) 2026-06-22 02:30:48 +00:00
Aditya Singh b20cb7f897 fix(approvals): skip needs_approval_checker when status resolved in _collect_runs_by_approval (#3259) 2026-06-22 11:10:56 +09:00
Aditya Singh 9f93077a74 fix(run): cancel sibling guardrail tasks when one raises (#3239) 2026-06-22 11:07:06 +09:00
c 83e8a1b6e2 fix: #3348 make AdvancedSQLiteSession add_items atomic (#3349) 2026-06-22 10:44:55 +09:00
c 13ef230468 fix: #3346 clean up branch-only messages when deleting branches (#3347) 2026-06-22 10:42:00 +09:00
Kazuhiro Sera 869e869c70 docs: translate pages 2026-06-19 15:42:00 +09:00
Kazuhiro Sera 306d426930 docs: changes for #3487 feature addition (#3488) 2026-06-19 15:19:17 +09:00
Kazuhiro Sera f918c6a4f0 docs: #3461 changes for tool_not_found_behavior option (#3462) 2026-06-19 15:05:53 +09:00
github-actions[bot] 510b7de2ce Release 0.17.6 (#3659) 2026-06-19 15:02:31 +09:00
Mohammed Siddiq 09f0ed45e7 fix: enforce the documented strict JSON-compatible contract for #3486 (#3657) 2026-06-18 08:26:47 +00:00
Kazuhiro Sera 7fc489eb0d feat: add SDK-only custom data for tool outputs (#3486) 2026-06-18 12:38:28 +09:00
Kazuhiro Sera a4ba63f704 feat: add pre-approval tool input guardrails (#3487) 2026-06-18 12:38:15 +09:00
Kazuhiro Sera 288455911c fix: suppress handoff whitespace tool-name warnings (#3652) 2026-06-18 10:29:58 +09:00
Kazuhiro Sera 12e268c8e2 chore: improve pr-draft-summary skill trigger 2026-06-18 10:29:35 +09:00
Kazuhiro Sera c359c20647 docs: update translated pages 2026-06-13 15:16:25 +09:00
Kazuhiro Sera 131c3aef76 docs: tweak examples and senteneces 2026-06-13 15:16:05 +09:00
MUHAMMAD SALMAN HUSSAIN 1b0076dda0 fix(docs): fix typo in sandbox guide (#3628) 2026-06-13 08:26:45 +09:00
github-actions[bot] d8068d96a9 Release 0.17.5 (#3619) 2026-06-11 13:10:23 +09:00
MUHAMMAD SALMAN HUSSAIN 5a3028f37c docs: fix subject-verb agreement in agent loop description (#3605) 2026-06-09 23:16:32 +00:00
MUHAMMAD SALMAN HUSSAIN b855c76a56 docs: capitalization fix in tracing docs (#3602) 2026-06-09 23:14:40 +00:00
MUHAMMAD SALMAN HUSSAIN a4d17da8ae docs: improve code snippet in tools documentation (#3599) 2026-06-09 02:55:01 +00:00
MUHAMMAD SALMAN HUSSAIN 6927622331 docs: tweak in usage doc (#3597) 2026-06-09 02:53:25 +00:00
qiyaoq-oai 8eaa4b9872 fix: expose sandbox error retryability (#3581)
Context: https://github.com/temporalio/sdk-python/issues/1548

This pull request adds provider-neutral retryability metadata for
sandbox failures.

- Adds `SandboxError.retryable` with `True`, `False`, and `None` for
unknown classification.
- Propagates retryability through wrapped sandbox errors.
- Emits retryability in sandbox finish events and trace error payloads.
- Classifies clear terminal/transient cases across sandbox providers
without exposing provider internals to integrations.
- Adds focused tests for core error behavior, provider classifiers, and
observability.
2026-06-05 10:53:06 -07:00
Kazuhiro Sera 5121f302a5 docs: translate pages 2026-06-05 09:53:07 +09:00
William f4e5d96f9f docs: add Latitude to external tracing processors list (#3577) 2026-06-04 23:03:01 +00:00
John CSA b051a70393 test: add unit tests for _openai_retry helpers (#3544) 2026-06-04 07:38:26 +00:00
John CSA 0e9807b6c4 docs: fix two docstring grammar errors in tool.py (#3543) 2026-06-04 07:36:13 +00:00
John CSA bf0d025dc9 test: add unit tests for run_demo_loop streaming, EOF, and empty-input paths (#3542) 2026-06-04 07:32:26 +00:00
MUHAMMAD SALMAN HUSSAIN 9470af01ed docs: fix docstring typo in stdio params env description (#3557) 2026-06-04 07:19:52 +00:00
jdoughty04 9520a5c558 chore: bump Modal sandbox extra to 1.4.3 (#3538) 2026-06-04 16:17:58 +09:00
John CSA 464043a5e6 docs: add missing space in MCP params docstrings (#3535) 2026-05-31 05:07:48 +00:00
John CSA bd8b1b7541 fix: use tuple form for SpeechGroupSpanData __slots__ (#3534) 2026-05-31 05:07:10 +00:00
Kazuhiro Sera d87fec8589 docs: remove beta label from realtime agent docs 2026-05-30 08:10:04 +09:00
Alex Bevilacqua 9411cee8e2 docs: add MongoDB session example under examples/memory (#3036) 2026-05-28 09:37:00 +00:00
Kazuhiro Sera 921135630b fix: #3512 type tool-end hook results as object (#3518) 2026-05-28 17:57:33 +09:00
github-actions[bot] 6d5b888f6f Release 0.17.4 (#3505) 2026-05-26 17:53:21 +09:00
lionel-oai 9a92ea4c8e Support Realtime custom voice objects (#3473) 2026-05-26 17:39:40 +09:00
rmotgi1227 fedc809afd fix: export MCPListToolsItem, ToolSearchCallItem, and ToolSearchOutputItem from agents (#3490) 2026-05-22 01:08:07 +00:00
rmotgi1227 573530febb fix: export more tracing related functions & types from agents (#3489) 2026-05-22 09:59:58 +09:00
Shaurya Singh 813a00324e fix: redact invalid JSON payload in ModelBehaviorError data (#3485) 2026-05-21 23:54:12 +00:00
rmotgi1227 eda7b51aea fix: add missing entries to span __slots__ (#3483) 2026-05-21 22:06:41 +00:00
Kazuhiro Sera 45effb4b7d fix: #3459 add opt-in recovery for missing function tools (#3461) 2026-05-21 10:46:44 +09:00
rmotgi1227 9303389d84 fix: use non-None value for output in FunctionSpanData (#3475) 2026-05-21 10:03:01 +09:00
Illia Oleksiuk 9514473c23 fix: apply hardened http client default to MCP SSE transport (#3466) 2026-05-20 15:14:47 +09:00
Kazuhiro Sera 445ad2273c docs: add SECURITY.md in the same way with openai-agents-js repo 2026-05-20 12:38:30 +09:00
github-actions[bot] 17f7caeaa3 Release 0.17.3 (#3417) 2026-05-19 10:24:42 +09:00
Adrian f6ba91b120 Runtime handling updates (#3451)
## Summary
- Refresh runtime handling around session and tool-call flows.
- Adjust model configuration metadata used by runtime integrations.
- Add focused coverage for the updated behavior.

## Validation
- .venv/bin/python -m pytest tests/model_settings/test_serialization.py
tests/models/test_trace_config.py
tests/mcp/test_streamable_http_client_factory.py
tests/test_run_context_approvals.py
tests/test_run_state.py::TestRunState::test_trace_api_key_serialization_is_opt_in
tests/realtime/test_session.py
- .venv/bin/ruff check <touched files>
- .venv/bin/ruff format --check <touched files>
- git diff --check
2026-05-18 16:53:20 -07:00
Shaurya Singh 65774ce88d docs: fix duplicated word in usaspending glossary example (#3445) 2026-05-18 17:05:16 +09:00
Kazuhiro Sera 13d1815218 docs: re-fix #3444 2026-05-18 17:03:06 +09:00
Nachiket Torwekar 41fe113dd0 docs: fix LiteLLM API reference redirect (#3444) 2026-05-18 07:05:30 +00:00
Kazuhiro Sera 4970fd6ce4 fix: keep mountpoint credentials out of sandbox commands (#3429) 2026-05-18 11:30:31 +09:00
c 4bd459e403 fix: #3363 honor short custom voice splitter chunks (#3364) 2026-05-16 10:04:23 +09:00
Matthew.K e37b3d266b fix: normalize leading question marks in exposed port queries (#3424) 2026-05-16 09:59:39 +09:00
Matthew.K 94523f946e fix: reject relative sandbox workspace roots (#3422) 2026-05-16 09:47:27 +09:00
Tianyu Cai cb0461d177 fix: log exception when output guardrail raises instead of silently ignoring (#3411) 2026-05-16 09:39:27 +09:00
Illia Oleksiuk 5e71d09554 fix: guard None text in ItemHelpers.extract_last_content (#3394) 2026-05-15 15:40:30 +09:00
Illia Oleksiuk cb7211b599 fix: filter hosted_tool_call types in remove_all_tools handoff filter (#3386) 2026-05-15 15:40:04 +09:00
Tianyu Cai 43a389d462 fix: skip wait_for_status when Vercel sandbox is in a terminal state (#3410) 2026-05-15 15:39:35 +09:00
c 656baf8ead fix: #3357 output schema names for Literal types (#3358) 2026-05-14 19:24:35 +09:00
Illia Oleksiuk eca794c0bc fix: avoid mutating codex output schema input (#3385) 2026-05-14 12:49:48 +09:00
Illia Oleksiuk 7865ec9819 fix: avoid mutating FunctionTool params_json_schema (#3382) 2026-05-14 12:48:57 +09:00
Kazuhiro Sera f7e8196484 chore: clean up CI jobs and update uv pin (#3400) 2026-05-14 12:36:41 +09:00
Drew Hintz bdd228b4db [codex] Harden release tag workflow (#3399)
## Summary

- Require release-tag PRs to come from the same repository before
creating tags.
- Preserve the existing merged-PR and `release/v*` branch gates.

## Validation

- Parsed `.github/workflows/release-tag.yml` with PyYAML.
2026-05-13 21:58:31 -05:00
Illia Oleksiuk 900cab6212 docs: document auto_previous_response_id (#3383) 2026-05-13 23:35:44 +00:00
Kazuhiro Sera 8dc30e4807 docs: translate all pages using new settings (#3392) 2026-05-14 07:53:49 +09:00
Illia Oleksiuk f9eb3a4f33 docs: mark Agent.instructions as optional (#3384) 2026-05-13 15:31:51 +09:00
Kazuhiro Sera ec016cde9a fix: unify memory optional dependency import errors (#3389) 2026-05-13 11:13:56 +09:00
Kazuhiro Sera 564584513f docs: add SDK review guidance (#3376) 2026-05-12 16:05:42 +09:00
Kazuhiro Sera a466860fdc ci: disable auto labeling job 2026-05-12 15:47:02 +09:00
zhoufengen 03ff10ef6c fix: guard None text in text_message_output and add output guardrail count to RunErrorDetails (#3375) 2026-05-12 14:53:34 +09:00
Kazuhiro Sera 55b859d05c ci: tweak the PR labeling operation 2026-05-12 14:41:56 +09:00
Kazuhiro Sera 76f42d8ed7 ci: tweak the PR labeling operation 2026-05-12 14:37:28 +09:00
github-actions[bot] 55e4a850fc Release 0.17.2 (#3368) 2026-05-12 12:13:02 +09:00
github-actions[bot] 5594fb464d docs: update translated document pages (#3371) 2026-05-12 08:19:18 +09:00
c 64de1cb211 fix: #3310 avoid empty chat tool outputs (#3312) 2026-05-11 23:14:46 +00:00
c 1d3df7fa04 docs: document sandbox archive limits after #3278 release (#3311) 2026-05-12 08:11:23 +09:00
Kazuhiro Sera ae3263b840 docs: normalize memory docstring cross-references (#3370) 2026-05-11 23:03:30 +00:00
c e3c99d9964 fix: #3361 honor session settings in AsyncSQLiteSession (#3362) 2026-05-12 08:01:39 +09:00
c b2bd8218c6 fix: #3359 preserve local approval rejection reasons (#3360) 2026-05-11 22:32:46 +00:00
Kazuhiro Sera 8715a0585a fix: avoid auto response for unknown realtime tools (ref: #3287) (#3366) 2026-05-12 07:27:59 +09:00
c 4a95659892 fix: #3354 interrupt tracing retry backoff on shutdown (#3355) 2026-05-12 07:23:11 +09:00
Kazuhiro Sera 5635fab9d3 fix: #3268 fix OpenAI Conversations reasoning persistence (#3352) 2026-05-12 07:20:47 +09:00
github-actions[bot] 92e014a4cc docs: update translated document pages (#3351) 2026-05-11 16:37:55 +09:00
Kazuhiro Sera 852a8dbad4 docs: clarify max_delay for retries works (#3350) 2026-05-11 16:29:20 +09:00
github-actions[bot] eada610734 Release 0.17.1 (#3290) 2026-05-11 15:33:41 +09:00
Kazuhiro Sera 028abc6a74 fix: make tracing shutdown best-effort on process exit (#3343) 2026-05-11 15:19:32 +09:00
Kazuhiro Sera 4c3de2df65 docs: update MCP examples (#3342) 2026-05-11 11:34:56 +09:00
Sihan Sun cf151f91ff fix: #781 replace assertion in handoff() with UserError (#3339) 2026-05-11 08:19:59 +09:00
Kazuhiro Sera 970db97acb fix: #3333 scope Realtime tool approvals by qualified key (#3340) 2026-05-11 08:12:29 +09:00
Kazuhiro Sera 4bc942af3c fix: #3267 preserve required hosted tool IDs in OpenAI conversation sessions (#3341) 2026-05-11 08:07:05 +09:00
c 52656a51cb fix: #3330 handle string tool trimmer allowlists (#3331) 2026-05-11 07:24:45 +09:00
c 479640e214 fix: #3308 reject chat custom tool calls explicitly (#3309) 2026-05-10 17:32:49 +09:00
c 650212ef62 fix: #3313 align multi-choice chat streams with strict validation (#3314) 2026-05-10 16:28:29 +09:00
c d7417fb2e7 fix: #3319 preserve nested handoff history content (#3320) 2026-05-10 16:24:27 +09:00
Kazuhiro Sera a6a4cc5143 feat: improve examples auto-run coverage and artifact handling (#3328) 2026-05-10 14:25:47 +09:00
Kazuhiro Sera 94ba76de0f fix: include sandbox provider error details (#3326) 2026-05-10 12:38:31 +09:00
c 62560996c2 fix: #3317 return fresh empty strict schemas (#3318) 2026-05-10 08:54:25 +09:00
c 94fa9e21ba fix: #3315 align generic dict output schemas (#3316) 2026-05-10 08:54:16 +09:00
c 610c2742dc fix: #3306 track MongoDB metadata timestamps (#3307) 2026-05-10 08:54:01 +09:00
c 4b8744903a fix: #3304 skip corrupt items during pop (#3305) 2026-05-10 08:53:26 +09:00
c fa75ffc404 fix: #3274 limit sandbox archive extraction (#3278) 2026-05-10 08:52:55 +09:00
Kazuhiro Sera bc3607bae4 fix: preserve GitRepo root subpath aliases (#3303) 2026-05-09 12:06:45 +00:00
Kazuhiro Sera 9154d836a2 fix: allow empty GitRepo subpaths as repository root (#3299) 2026-05-09 07:54:00 +00:00
Kazuhiro Sera 1289fb0bef fix: make chat completions response-feature validation opt-in (#3298) 2026-05-09 16:46:47 +09:00
Kazuhiro Sera 73bc963398 chore: improve automated example coverage and local service handling (#3297) 2026-05-09 16:17:49 +09:00
Kazuhiro Sera 43e051e725 fix: guard no-op tracing span IDs (#3296) 2026-05-09 14:19:24 +09:00
Kazuhiro Sera 38bef807f5 test: guard Responses transport extra kwargs with official client (#3295) 2026-05-09 04:42:39 +00:00
Kazuhiro Sera fc1abe0999 Revert "fix(models): allow extra_query/extra_body via extra_args in Responses" (#3294) 2026-05-09 04:28:16 +00:00
Aditya Singh dbb3181386 fix(tracing): keep BatchTraceProcessor worker alive on exporter errors (#3216) 2026-05-09 13:17:06 +09:00
Aditya Singh 3031b13eaa fix(realtime): validate RealtimeAgent fields in __post_init__ (#3234) 2026-05-09 12:54:03 +09:00
Aditya Singh 8f40dde4a4 fix(litellm): avoid duplicating content and signed thinking blocks across parallel tool-call splits (#3215) 2026-05-09 12:52:11 +09:00
Aditya Singh 4bb388c955 fix(redis-session): preserve created_at across writes (#3202) 2026-05-09 12:51:03 +09:00
Aditya Singh 29b2acffb1 fix(handoffs): preserve HandoffInputData.input_items in remove_all_tools (#3253) 2026-05-09 12:50:16 +09:00
Aditya Singh f3d434cdfd fix(voice): stop AudioInput.to_base64() from mutating caller's buffer (#3201) 2026-05-09 12:48:48 +09:00
github-actions[bot] 33b9a2c9fd docs: update translated document pages (#3293) 2026-05-09 12:12:05 +09:00
Yaron Schneider 272dd18b9f docs: add dapr to durable orchestration integrations (#3292) 2026-05-09 11:53:05 +09:00
c cc2998845b fix: #3284 wake realtime event iterators on close (#3285) 2026-05-09 11:50:59 +09:00
c 035271db60 fix: #3282 reject unsupported Chat Completions reusable prompts (#3283) 2026-05-09 11:49:39 +09:00
c 55eb3dec30 fix: #3273 validate git repo subpaths (#3276) 2026-05-09 11:47:50 +09:00
Aditya Singh f8ba94d416 fix(realtime): treat None audio.input/audio.output as unset (#3254) 2026-05-09 11:45:36 +09:00
Aditya Singh 7aeb39e150 fix(sessions): skip corrupt docs in MongoDBSession.pop_item (#3247) 2026-05-09 11:44:54 +09:00
Aditya Singh 7e9089f270 fix(realtime): preserve output_audio content parts in output_item events (#3230) 2026-05-09 11:44:14 +09:00
Quratulain-bilal 960e979f74 fix: await cancelled output guardrail tasks on tripwire (#3187) 2026-05-09 11:43:15 +09:00
Aditya Singh e6a3ed887a fix: avoid duplicating content and signed thinking blocks across parallel tool-call splits (#3261) 2026-05-09 02:48:56 +09:00
Aditya Singh e86dff2907 fix: exclude Computer instances from provider duck-typing (#3249) 2026-05-09 02:45:31 +09:00
Aditya Singh 12ad112fec fix(realtime): raise UserError for input_type without on_handoff (#3248) 2026-05-09 02:44:54 +09:00
Aditya Singh 250fb97fef fix(run): preserve last known response_id on conversation resume (#3245) 2026-05-09 02:42:05 +09:00
Aditya Singh 62f9416ead fix(realtime): skip invalid input_text parts in user input conversion (#3243) 2026-05-09 02:41:12 +09:00
Aditya Singh 76702572ef fix: skip needs_approval_checker when status already resolved (#3229) 2026-05-09 02:37:35 +09:00
Aditya Singh 1b6876a8c2 fix(sessions): persist output_tokens_details when input details are None (#3227) 2026-05-09 02:36:18 +09:00
Aditya Singh 89f368df03 fix: await on_handoff callables with async __call__ (#3211) 2026-05-09 02:34:17 +09:00
Aditya Singh 730ee55e14 fix(mcp): isolate strict schema conversion from non-strict fallback (#3199) 2026-05-09 02:33:38 +09:00
c b4741e077d fix: #3288 normalize RunState guardrail payloads (#3289) 2026-05-09 02:18:02 +09:00
c 4a3d33e44f fix: #3280 streaming guardrail exception cleanup (#3281) 2026-05-09 02:16:03 +09:00
Aditya Singh 9242902e1b fix(run): preserve failed status across apply_patch operations (#3217) 2026-05-09 02:08:21 +09:00
Aditya Singh b4be17586f fix(realtime): preserve existing transcript over stale delta accumulator (#3214) 2026-05-09 02:07:52 +09:00
Aditya Singh ec5523d620 fix: preserve existing request_usage_entries on Usage.add (#3213) 2026-05-09 02:07:20 +09:00
Aditya Singh 1d38492b44 fix: drop reasoning items orphaned by dropped tool calls (#3207) 2026-05-09 02:06:58 +09:00
Aditya Singh f32f613a7f fix(strict-schema): preserve chained $ref during sibling-key expansion (#3205) 2026-05-09 02:05:20 +09:00
Aditya Singh de60d05b0c fix(models): allow extra_query/extra_body via extra_args in Responses (#3194) 2026-05-09 02:05:02 +09:00
Aditya Singh cc5a392583 fix: preserve tool guardrail results across handoffs in SingleStepResult (#3237) 2026-05-09 02:04:13 +09:00
Aditya Singh 8b04ee0939 fix(exceptions): export MCPToolCancellationError from top-level package (#3210) 2026-05-09 01:58:48 +09:00
c e19ac4e44d fix: #3286 send realtime output for unknown tool calls (#3287) 2026-05-08 16:55:10 +00:00
Aditya Singh c7bcdd4a4a fix(realtime): expose max_output_tokens on RealtimeSessionModelSettings (#3223) 2026-05-09 01:50:19 +09:00
c 58a89c810f fix: #3275 reject chat completions server state (#3279) 2026-05-08 16:46:23 +00:00
c 9a0c07f9c7 fix: #3270 Validate model retry backoff settings (#3272) 2026-05-09 01:40:28 +09:00
Aditya Singh 8619dfda75 fix: skip CompactionItem silently in stream queue helper (#3224) 2026-05-08 16:27:11 +00:00
github-actions[bot] 683b6e79e5 docs: update translated document pages (#3193) 2026-05-08 17:24:16 +09:00
Kazuhiro Sera e3746c52d9 docs: updates for v0.17.0 (#3188) 2026-05-08 17:10:34 +09:00
github-actions[bot] 0fea7e8347 Release 0.17.0 (#3191) 2026-05-08 17:07:36 +09:00
Kazuhiro Sera 0a76dd03ce docs: improve auto run for examples 2026-05-08 16:56:37 +09:00
Kazuhiro Sera f47d486985 fix: #3169 constrain local sandbox artifact sources to base dir (#3177) 2026-05-08 15:25:13 +09:00
Kazuhiro Sera 1660d306b5 feat: default realtime sessions to gpt-realtime-2 (#3190) 2026-05-08 15:24:41 +09:00
Abdulrahman Alfozan ee36d43584 Fix Responses extra_args collision with omitted kwargs (#3185)
### Summary

Fix a false duplicate-argument error when a Responses request parameter
is supplied through `ModelSettings.extra_args` and the first-class
request field is only present as OpenAI's `omit` sentinel.

### Test plan

- `make format`
- `make lint`
- `uv run pytest
tests/models/test_openai_responses.py::test_build_response_create_kwargs_allows_extra_arg_when_explicit_arg_is_omitted
tests/models/test_openai_responses.py::test_build_response_create_kwargs_rejects_duplicate_context_management_extra_args
tests/models/test_openai_responses.py::test_build_response_create_kwargs_rejects_duplicate_extra_args_keys
-q`
- `uv run mypy src/agents/models/openai_responses.py
tests/models/test_openai_responses.py`
- `uv run pyright src/agents/models/openai_responses.py
tests/models/test_openai_responses.py`
- `git diff --check`

### Issue number

N/A

### Checks

- [x] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [x] I've run `make lint` and `make format`
- [x] I've made sure tests pass where not blocked by unrelated
local-only failures
2026-05-07 16:23:13 -07:00
Kazuhiro Sera a91f630f79 fix: skip prerequisite-bound examples in auto runs 2026-05-07 20:03:01 +09:00
github-actions[bot] bd84b65258 Release 0.16.1 (#3167) 2026-05-07 20:00:54 +09:00
Kazuhiro Sera 28de3652d3 fix: #3168 validate MCP require_approval policies (#3179) 2026-05-07 18:26:48 +09:00
c a67d95f58a fix: #3174 count valid encrypted session items for limits (#3175) 2026-05-07 16:15:52 +09:00
Illia Oleksiuk 3a11cf5225 fix: reject non-object function tool input JSON (#3166) 2026-05-07 14:41:38 +09:00
Kazuhiro Sera 170ee73f94 fix: #3109 stabilize chat completions stream output indexes (#3176)
Co-authored-by: Aphroq <37263590+Aphroq@users.noreply.github.com>
2026-05-07 14:40:38 +09:00
c 6f5fbf6dbb fix: #3170 clean up git repo temp clones on failure (#3172) 2026-05-07 14:05:24 +09:00
c 516aa0c9d9 fix: #3171 reject corrupt Dapr session state updates (#3173) 2026-05-07 14:05:10 +09:00
c 0fb2e0944c fix: restore session history after compaction replacement failures (#3117) 2026-05-07 12:38:07 +09:00
github-actions[bot] eed9100777 docs: update translated document pages (#3165) 2026-05-07 10:00:27 +09:00
Kazuhiro Sera f185dfa2a0 docs: document tool execution concurrency (#3164) 2026-05-07 09:54:37 +09:00
github-actions[bot] c5ebf809ea docs: update translated document pages (#3163) 2026-05-07 09:36:28 +09:00
Kazuhiro Sera 1683357483 docs: add 0.16.0 changelog (#3153) 2026-05-07 09:29:51 +09:00
Kazuhiro Sera 0ed4ee6e18 docs: updates for #3147 (#3148) 2026-05-07 09:29:41 +09:00
github-actions[bot] 9f361ba7dd Release 0.16.0 (#3150) 2026-05-07 09:19:36 +09:00
github-actions[bot] e8856de1b4 docs: update translated document pages (#3162) 2026-05-07 09:02:55 +09:00
mindbomber 5a10e46f11 docs: realtime guardrail fallback behavior (#3157) 2026-05-06 23:50:27 +00:00
Kazuhiro Sera 8c8a2eb32e fix: #3104 stabilize chat completions tool call output indexes (#3161) 2026-05-07 08:49:55 +09:00
github-actions[bot] ff8e3db4b2 docs: update translated document pages (#3160) 2026-05-07 08:45:27 +09:00
Kazuhiro Sera 8526723b49 feat: #1859 add runtime function tool concurrency config (#3152) 2026-05-07 08:40:30 +09:00
MAV 0466636b77 feat: #1167 add opt-in server-prefixed MCP tool names (#3019) 2026-05-07 08:40:21 +09:00
Illia Oleksiuk f903926394 fix: make Permissions hashable to match User and Group (#3154) 2026-05-07 08:38:16 +09:00
github-actions[bot] 1a1b35d4fb docs: update translated document pages (#3151) 2026-05-06 21:21:34 +09:00
Kazuhiro Sera fc2d208f30 feat: switch the default model to a newer mini model (affecting only when a model is unset) (#3147) 2026-05-06 21:14:51 +09:00
Kazuhiro Sera b9cbab149f feat: allow disabling max_turns with None (#3132) 2026-05-06 21:14:27 +09:00
c bed924b45d fix: reject external symlink targets during hydrate (#3094) 2026-05-06 21:13:53 +09:00
github-actions[bot] e1cb2be4ca Release 0.15.3 (#3149) 2026-05-06 21:09:15 +09:00
Quratulain-bilal b1722a7459 fix: tolerate audio deltas before audio format negotiation in ModelAu… (#3141) 2026-05-06 19:01:41 +09:00
Aditya Singh 0370fd3527 test(realtime): cover overlapping tool response creates (#3140) 2026-05-06 18:57:22 +09:00
Aditya Singh 9a2b4a9b85 fix(mcp): make duplicate tool errors deterministic (#3136) 2026-05-06 17:37:14 +09:00
Aditya Singh e22f25a431 fix(mcp): reject non-object tool input JSON (#3135) 2026-05-06 17:36:30 +09:00
Aditya Singh 6e691ee2ea fix(mcp): avoid mutating tool input schemas (#3134) 2026-05-06 17:34:49 +09:00
github-actions[bot] ce462354fd docs: update translated document pages (#3131) 2026-05-06 09:50:41 +09:00
Kazuhiro Sera 02a6b21151 docs: updates for #3128 (#3129) 2026-05-06 09:37:58 +09:00
github-actions[bot] 75da8e0200 Release 0.15.2 (#3099) 2026-05-06 09:33:20 +09:00
c 3d1231e0fe fix: redact function tool trace span errors (#3111) 2026-05-06 00:30:48 +09:00
Kazuhiro Sera 601ecf5503 fix: #3123 avoid replaying assistant conversation item IDs for OpenAIConversationsSession (#3127) 2026-05-05 20:55:29 +09:00
Kazuhiro Sera 574a598fae feat: add context management model setting (#3128) 2026-05-05 20:55:16 +09:00
c 7a5d32bc83 fix: block disabled function tools before execution (#3118) 2026-05-05 09:43:09 +09:00
Felmon 613b8f39a6 fix(mcp): isolate merged tool metadata (#3114) 2026-05-05 09:41:09 +09:00
c 9b57f057b4 fix: reject failed responses stream terminals (#3107) 2026-05-04 22:20:46 +09:00
c ae60947451 fix: redact MCP invalid JSON errors when tool logging is disabled (#3088) 2026-05-04 22:14:01 +09:00
Quratulain-bilal 1b7d878b7c test: add direct unit tests for _mcp_tool_metadata helpers (#3102) 2026-05-04 18:00:20 +09:00
Quratulain-bilal b80d541946 test: add direct unit tests for _tool_identity helpers (#3101) 2026-05-04 17:59:43 +09:00
Quratulain-bilal 54ec5f0091 test: cover real Handoff object branch in visualization (#3100) 2026-05-04 17:58:14 +09:00
c 3854c124cb fix: only rewind matching session suffixes (#3090) 2026-05-04 10:05:37 +09:00
Illia Oleksiuk 63ebf5ada1 fix: make ToolContext hashable to match RunContextWrapper (#3097) 2026-05-04 09:58:28 +09:00
Quratulain-bilal fbc5a44045 test: cover on_handoff, on_tool_start, on_tool_end on RunHooks (#3098) 2026-05-04 00:58:08 +00:00
Quratulain-bilal 4bb4400731 fix: filter custom_tool_call types in remove_all_tools handoff filter (#3095) 2026-05-04 09:55:20 +09:00
c 4b5a0b89cd fix: reject string-like shell commands (#3092) 2026-05-04 09:50:59 +09:00
c 9d24382d0e test: add realtime tool output serialization edge cases (#3077) 2026-05-04 09:43:14 +09:00
c 044d44ce0d test: cover realtime tool timeout behaviors in realtime session (#3076) 2026-05-04 09:42:47 +09:00
Kazuhiro Sera f2fb9ffb66 test: improve coverage and organize test layout (#3085) 2026-05-02 15:40:54 +09:00
github-actions[bot] 60b7bee807 docs: update translated document pages (#3084) 2026-05-02 14:19:23 +09:00
Kazuhiro Sera e9a3e3610c docs: updates for #3080 (#3081) 2026-05-02 14:09:31 +09:00
github-actions[bot] ceb238fd1b Release 0.15.1 (#3083) 2026-05-02 11:19:33 +09:00
Kazuhiro Sera 41c646d898 fix: restore UnixLocal PTY terminal signal defaults (#3082) 2026-05-02 00:30:19 +00:00
Kazuhiro Sera 4b2881c7c4 feat: expose Responses WebSocket keepalive options (#3080) 2026-05-02 09:18:45 +09:00
c a47b7ea7ec fix: #3074 restore SIGINT defaults for UnixLocal PTY children (#3075) 2026-05-02 09:16:36 +09:00
c 42c3015518 chore: harden Dapr Redis integration fixture loading (#3078) 2026-05-02 09:15:41 +09:00
Quratulain-bilal ae224b4449 test: cover guardrail name fallback to function __name__ (#3073) 2026-05-02 08:14:47 +09:00
github-actions[bot] 756fa431a7 docs: update translated document pages (#3072) 2026-05-01 17:47:40 +09:00
Kazuhiro Sera 841f72f296 docs: improve quickstart documentation for Windows OS users (#3071) 2026-05-01 08:35:29 +00:00
github-actions[bot] 611d080ff0 docs: update translated document pages (#3064) 2026-05-01 15:52:30 +09:00
Kazuhiro Sera 48d7e9cae7 docs: add 0.15 changelog (#3058) 2026-05-01 15:45:49 +09:00
github-actions[bot] f7410c8e96 Release 0.15.0 (#3063) 2026-05-01 15:42:28 +09:00
Kazuhiro Sera da3f15708e ci: improve translation pipelone to be more robust 2026-05-01 15:32:07 +09:00
dependabot[bot] 498390a741 chore(deps): bump openai/codex-action from 1.6 to 1.8 (#3060) 2026-05-01 14:31:21 +09:00
dependabot[bot] 7833715ac2 chore(deps): bump pypa/gh-action-pypi-publish from 1.13.0 to 1.14.0 (#3061) 2026-05-01 14:31:04 +09:00
dependabot[bot] d996707c0a chore(deps): bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 (#3062) 2026-05-01 14:30:06 +09:00
dependabot[bot] ec99da6375 chore(deps): bump actions/github-script from 8.0.0 to 9.0.0 (#3059) 2026-05-01 14:29:30 +09:00
Kazuhiro Sera 2d40c09c88 fix: #3055 surface model refusals during run resolution (#3057) 2026-05-01 14:28:13 +09:00
Gopal Bagaswar 3a3f34f18d docs: add missing space after period in MCPServerStdio docstring (#3053) 2026-04-30 12:19:20 +09:00
github-actions[bot] 7029ea8fff Release 0.14.8 (#3049) 2026-04-29 12:39:00 +09:00
ateamofantsintheirprime 572c7bf1b5 docs: fix typo in comment for WS event handler (#3050) 2026-04-29 01:56:29 +00:00
Kazuhiro Sera 0661c9e9ca fix: #3043 delimit sandbox prompt instruction sections (#3047) 2026-04-29 10:40:48 +09:00
Kazuhiro Sera 05004336a2 fix: #3046 preserve MCP re-export import errors (#3048) 2026-04-29 01:40:17 +00:00
github-actions[bot] 8d7f05b6b2 Release 0.14.7 (#3031) 2026-04-28 15:45:35 +09:00
Abdulrahman Alfozan ebdb0f2ee1 fix: add GPT-5.5 aliases to sandbox compaction (#3039)
### Summary

Adds GPT-5.5 snapshot and pro aliases to the sandbox compaction model
context-window map so compaction threshold calculation recognizes them
as 1,047,576-token models.

### Test plan

- `uv run ruff check src/agents/sandbox/capabilities/compaction.py
tests/sandbox/test_compaction.py`
- `uv run pytest tests/sandbox/test_compaction.py`
- Verified `CompactionModelInfo.for_model()` locally for
`gpt-5.5-2026-04-23`, `gpt-5.5-pro`, and `gpt-5.5-pro-2026-04-23`
- Verified the model IDs exist via the OpenAI Models API; also ran a
live Responses API smoke with `gpt-5.5-2026-04-23`

### Issue number

N/A

### Checks

- [x] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [ ] I've run `make lint` and `make format`
- [x] I've made sure tests pass
2026-04-28 06:34:34 +00:00
Andi Liu b3688db750 [sandbox] Raise Phase 2 memory consolidation turn limit (#3038)
### Summary

- Phase 2 sandbox memory consolidation can need more than the default
runner turn cap when rewriting memory files.
- Pass `max_turns=500` for the Phase 2 consolidation agent only.
2026-04-27 16:39:46 -07:00
Federico 8025ed0b42 Fix: remove unset fields from calls to Responses API (#3026) 2026-04-27 09:50:10 +09:00
Matthew.K ba889de480 fix: reject symlinked LocalFile sources (#2972) 2026-04-26 11:15:12 +09:00
Ali jawwad 5df41d3013 feat: #2886 add convenience properties (tool_name, call_id) to tool items (#3027)
Co-authored-by: Daniel Cufiño <dancufino@gmail.com>
2026-04-26 10:32:30 +09:00
Matthew.K 2eb8713b53 fix: tighten tar and zip member validation (#3028) 2026-04-26 10:24:36 +09:00
github-actions[bot] 9a207b6938 Release 0.14.6 (#3022) 2026-04-25 11:30:43 +09:00
github-actions[bot] 9af6ad111c docs: update translated document pages (#3023) 2026-04-25 11:14:50 +09:00
Alex Bevilacqua 1821bf8094 docs: add MongoDB session documentation (#3015) 2026-04-25 11:07:31 +09:00
github-actions[bot] 071e2b68f6 docs: update translated document pages (#3021) 2026-04-25 10:49:51 +09:00
Abdulrahman Alfozan c88f339d32 Update examples and defaults to GPT-5.5 (#3016) 2026-04-25 10:31:54 +09:00
mathis obadia 5ffc1ecee4 relax websockets upper bound from <16 to <17 (#3013) 2026-04-24 08:06:24 +09:00
mcgrew-oai c2cb031461 chore: harden uv dependency resolution (#3014) 2026-04-24 08:03:31 +09:00
github-actions[bot] fe3a5e6c27 Release 0.14.5 (#3007) 2026-04-23 11:19:40 +09:00
Kazuhiro Sera 16e040929b fix: #3004 serve HITL resume tool outputs (#3006) 2026-04-23 10:36:15 +09:00
Kazuhiro Sera 5be06a16a9 feat: #3001 add Modal sandbox idle timeout option (#3005) 2026-04-23 09:40:23 +09:00
ankitphogat 81c57c5e7e fix: backfill streamed terminal output (#3000) 2026-04-23 09:32:44 +09:00
github-actions[bot] 638388ad17 docs: update translated document pages (#2999) 2026-04-22 10:35:42 +09:00
Abdulrahman Alfozan 734d42490a docs: clarify lazy skill source host paths (#2998) 2026-04-22 10:26:28 +09:00
github-actions[bot] 4e43cbaf09 Release 0.14.4 (#2989)
### Release readiness review (v0.14.3 -> TARGET
ba3b17740b280c00330d9cd61158f88a34d28d2a)

This is a release readiness report done by `$final-release-review`
skill.

### Diff


https://github.com/openai/openai-agents-python/compare/v0.14.3...ba3b17740b280c00330d9cd61158f88a34d28d2a

### Release call:
**🟢 GREEN LIGHT TO SHIP** Patch bump to `0.14.4` with additive sandbox
capability and broad compatibility-focused test coverage; no concrete
release-blocking issues found in the diff.

### Scope summary:
- 34 files changed (+2236/-536); key areas touched:
`src/agents/sandbox/session/` refactors/extractions, new `BoxMount`
support in sandbox mount providers, provider integrations (`cloudflare`,
`vercel`, `daytona`, `e2b`, `blaxel`), sandbox docs, and substantial
sandbox compatibility/regression tests.
- Commit range reviewed (oldest to newest): docs cleanup/translation
updates, sandbox compatibility guards, snapshot default fix, Box mount
feature, shared mount lifecycle refactor, shared tar exclude refactor,
session helper extraction, version bump to `0.14.4`.

### Risk assessment (ordered by impact):
No material risks identified.

### Notes:
- Base tag determined from local tags only per instruction: `v0.14.3`.
- Target resolved from current `HEAD`:
`ba3b17740b280c00330d9cd61158f88a34d28d2a`.
- Assessment is based on diff/log/code inspection and added tests
in-range; no additional local test execution was performed in this CI
review step.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-21 12:22:38 -07:00
github-actions[bot] fdf2d009a6 docs: update translated document pages (#2996)
Automated update of translated documentation.

Triggered by commit:
[4c5112cbf4](https://github.com/openai/openai-agents-python/commit/4c5112cbf4b4467336939965fbfa28ad623b9df4).
Message: `feat: add BoxMount support (#2988)

### Summary

This pull request adds Box as an rclone-backed sandbox mount provider.

- Adds `BoxMount` with Docker rclone volume-driver support and
in-container `RcloneMountPattern` config generation.
- Wires Box into the sandbox entry exports and provider docs.
- Updates rclone-backed sandbox extension wording for Daytona, E2B, and
Runloop.
- Adds Docker and rclone mount config tests for Box auth/path options.

### Test plan

- `bash .agents/skills/code-change-verification/scripts/run.sh` *(format
and lint passed; typecheck failed on pre-existing local ignored
`tests/local` symlink files and unrelated Temporal example dependency
typing)*
- `uv run pyright --project pyrightconfig.json src/agents/sandbox
src/agents/extensions/sandbox tests/sandbox/test_mounts.py
tests/sandbox/test_docker.py`
- `uv run mypy src/agents/sandbox src/agents/extensions/sandbox
tests/sandbox/test_mounts.py tests/sandbox/test_docker.py`
- `uv run pytest -q tests/sandbox/test_mounts.py
tests/sandbox/test_docker.py`

### Issue number

N/A

### Checks

- [x] I've added new tests (if relevant)
- [x] I've added/updated the relevant documentation
- [x] I've run `make lint` and `make format`
- [x] I've made sure tests pass

Co-authored-by: Carter Rabasa <carter.rabasa@gmail.com>`

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-21 12:22:28 -07:00
Kazuhiro Sera 333721d72f refactor: extract sandbox session helper operations (#2985)
This pull request improves the sandbox session implementation by moving
archive extraction, manifest application, and snapshot lifecycle logic
out of `BaseSandboxSession` into focused helper modules. The existing
`BaseSandboxSession` method surface remains in place and delegates to
the new helpers, preserving provider overrides and compatibility while
reducing the size and responsibility concentration of the base session
class.
2026-04-21 11:52:04 -07:00
Kazuhiro Sera 4c68780ad3 refactor: share sandbox tar exclude arg generation (#2987)
This pull request improves sandbox workspace persistence internals by
sharing the shell `tar --exclude` argument generation used by Blaxel,
Daytona, and E2B sandbox sessions.

It adds a small common helper under `src/agents/sandbox/session/` and
keeps each provider's existing private `_tar_exclude_args()` surface as
a thin delegate, preserving the generated command strings while removing
duplicated quoting, sorting, and path-normalization logic. Direct unit
coverage was added for empty/dot paths, stable sorting, shell quoting,
dot-prefixed patterns, and absolute-path normalization.
2026-04-21 11:52:02 -07:00
Kazuhiro Sera 3aad7eba85 refactor: share sandbox ephemeral mount lifecycle (#2986)
This pull request improves sandbox backend persistence by extracting the
common ephemeral mount teardown and restore flow into a shared session
helper. Cloudflare and Vercel persistence now use the shared lifecycle
wrapper for persist and hydrate operations while preserving existing
archive error precedence and corruption context metadata.
2026-04-21 11:50:22 -07:00
Abdulrahman Alfozan 4c5112cbf4 feat: add BoxMount support (#2988)
### Summary

This pull request adds Box as an rclone-backed sandbox mount provider.

- Adds `BoxMount` with Docker rclone volume-driver support and
in-container `RcloneMountPattern` config generation.
- Wires Box into the sandbox entry exports and provider docs.
- Updates rclone-backed sandbox extension wording for Daytona, E2B, and
Runloop.
- Adds Docker and rclone mount config tests for Box auth/path options.

### Test plan

- `bash .agents/skills/code-change-verification/scripts/run.sh` *(format
and lint passed; typecheck failed on pre-existing local ignored
`tests/local` symlink files and unrelated Temporal example dependency
typing)*
- `uv run pyright --project pyrightconfig.json src/agents/sandbox
src/agents/extensions/sandbox tests/sandbox/test_mounts.py
tests/sandbox/test_docker.py`
- `uv run mypy src/agents/sandbox src/agents/extensions/sandbox
tests/sandbox/test_mounts.py tests/sandbox/test_docker.py`
- `uv run pytest -q tests/sandbox/test_mounts.py
tests/sandbox/test_docker.py`

### Issue number

N/A

### Checks

- [x] I've added new tests (if relevant)
- [x] I've added/updated the relevant documentation
- [x] I've run `make lint` and `make format`
- [x] I've made sure tests pass

Co-authored-by: Carter Rabasa <carter.rabasa@gmail.com>
2026-04-21 11:46:30 -07:00
Matthew.K 106ef05317 fix: ignore relative snapshot base overrides (#2976)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-04-21 22:54:25 +09:00
Kazuhiro Sera 2a515f0eb4 test: add sandbox compatibility guards (#2984) 2026-04-21 03:00:46 +00:00
github-actions[bot] 9e228fc959 docs: update translated document pages (#2982) 2026-04-21 10:24:08 +09:00
Abhishek Krishna bf3e9d178c docs: remove duplicate word in voice interruptions section (#2981) 2026-04-21 10:16:45 +09:00
github-actions[bot] 5d300f06da Release 0.14.3 (#2980) 2026-04-21 07:23:13 +09:00
Matthew.K 9d963e8f0c fix: bound manifest description truncation (#2974) 2026-04-20 22:03:50 +00:00
Matthew.K 902c5999a3 fix: tighten LocalSnapshot restorable checks (#2975) 2026-04-20 22:03:32 +00:00
Kazuhiro Sera 5515283d5e fix: windows errors with #2956 (#2979) 2026-04-20 21:58:07 +00:00
github-actions[bot] 35c497ebfb docs: update translated document pages (#2978) 2026-04-21 06:29:43 +09:00
Jonathan Arbaugh 66cc689742 Add Datadog as an external tracer in the tracing docs (#2965) 2026-04-21 06:23:27 +09:00
Kazuhiro Sera 12b5471aa3 fix: prepare Daytona workspace root before start (#2956) 2026-04-21 06:20:38 +09:00
Kazuhiro Sera cc57bb1648 fix: #2962 normalize sandbox paths and add Windows CI (#2963) 2026-04-21 06:20:17 +09:00
Kazuhiro Sera da82b2cd66 fix: #2951 warn for tool name character replacement (#2953) 2026-04-19 02:18:10 +00:00
Cocoon-Break cebc76397b docs: move module docstring to top of handoff_filters.py (#2950) 2026-04-19 01:23:00 +00:00
Kazuhiro Sera 82eaf15ad8 fix: #2938 make sandboxes importable on Windows (#2948) 2026-04-19 08:58:08 +09:00
github-actions[bot] e80d2d2319 Release 0.14.2 (#2899) 2026-04-18 09:15:14 +09:00
Nilesh Patil 61443ca8af fix: #2929 surface run-loop exceptions after stream_events() completes (#2931) 2026-04-18 09:01:57 +09:00
github-actions[bot] 55c8900736 docs: update translated document pages (#2935) 2026-04-18 08:38:20 +09:00
qiyaoq-oai 377204714d feat: support sandbox extra path grants (#2920)
- Add SandboxPathGrant manifest support for explicit access to absolute
paths outside sandbox workspace.
- Centralize path handling in WorkspacePathPolicy.normalize_path(...),
including extra grant matching, symlink-aware host validation, and
most-specific grant selection.
- Harden access boundaries by rejecting filesystem-root grants, // root
aliases, and grants that resolve to /.
- Preserve nested grant semantics, including writable parent + read-only
child cases through remote symlink targets and macOS exec confinement.
- Update sandbox provider integrations to use shared path policy across
Docker, Unix-local, Runloop, Vercel, Cloudflare, E2B, Modal, Daytona,
and Blaxel.
2026-04-17 15:26:51 -07:00
Steve Coffey dd3f59e399 Loosen sandbox compaction model parsing (#2930)
### Summary

This pull request fixes sandbox compaction defaults so Azure/custom
deployment names do not fail before the model request is sent. It makes
compaction model-window lookup separator-insensitive for known
OpenAI-style names like `gpt-5-2`, adds a non-throwing lookup path, and
falls back to the static compaction threshold when the model window
cannot be inferred.

### Test plan

- `make format`
- `make lint`
- `uv run pytest tests/sandbox/test_compaction.py
tests/sandbox/capabilities/test_compaction_capability.py
tests/test_sandbox_runtime_agent_preparation.py -q`
- `uv run mypy src/agents/sandbox/capabilities/compaction.py
tests/sandbox/test_compaction.py
tests/sandbox/capabilities/test_compaction_capability.py`
- `uv run pyright src/agents/sandbox/capabilities/compaction.py
tests/sandbox/test_compaction.py
tests/sandbox/capabilities/test_compaction_capability.py`

Full `make tests` / `make typecheck` are currently blocked in this
workspace by missing optional dependencies and unrelated existing
failures (`numpy`, `litellm`, `sqlalchemy`, `temporalio`, `boto3`,
runloop extra, and one PTY timing assertion).

### Issue number

Refs #2927

### Checks

- [x] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [x] I've run `make lint` and `make format`
- [ ] I've made sure tests pass
2026-04-17 11:22:06 -07:00
Alex Bevilacqua 67fb85a17f feat(extensions): add MongoDB session backend (#2902) 2026-04-17 21:44:23 +09:00
Kazuhiro Sera f84ef7f649 fix: normalize compacted Responses user inputs before session reuse (#2925) 2026-04-17 18:25:11 +09:00
Eric B b7ba44688d fix: #604 handle None choices in ChatCompletion response (#2850)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-04-17 14:07:20 +09:00
Scott Trinh b58d059f4d fix: Trust filesystem permissions for Vercel roots (#2910)
Instead of trying to constraint the agent to only work in the workspace,
allow it to fail freely without sudo.
2026-04-16 20:41:45 -07:00
Jason Steving 3ad12bc273 chore: Bump temporalio Dep in Temporal Example (#2918)
Version 1.26.0 of `temporalio` comes with sandbox agent support out of
the box. No more need for the temporary vendoring to backport the
functionality into the prior 1.25.x version. That was a temporary
workaround to ensure the example worked on day 1 since we (Temporal) had
to wait on making our release until after this project published 0.14.0
to avoid leaking the feature early.
2026-04-16 16:43:06 -07:00
yu 4f3c8a5379 fix: #1876 LiteLLM extra_body forwarding (#2900) 2026-04-16 06:34:22 +00:00
Kazuhiro Sera 5086b2490e docs: sync sandbox translations and set doc translation default model to gpt-5.4 (#2904) 2026-04-15 21:43:55 +00:00
github-actions[bot] b9b0141e27 docs: update translated document pages (#2903) 2026-04-16 05:38:03 +09:00
Kazuhiro Sera 6b14ebc824 docs: clarify OpenAI provider configuration guidance (#2901) 2026-04-15 20:26:13 +00:00
Kazuhiro Sera 47ecb38d07 feat: #2228 persist tool origin metadata in run items (#2654)
Co-authored-by: Hassan Abu Alhaj <136383052+habema@users.noreply.github.com>
2026-04-16 05:01:04 +09:00
Andrew Beveridge ☄️ 48ad4aae19 fix: tolerate None text in ResponseOutputText content items (#2883) 2026-04-16 04:55:46 +09:00
Javier De Jesus 09ea6aa420 fix: remove_all_tools missing hosted tool types (#2885) 2026-04-16 04:49:08 +09:00
github-actions[bot] 3dffa4ba93 Release 0.14.1 (#2895) 2026-04-16 04:24:41 +09:00
Abdulrahman Alfozan 2cef83b477 fix: sanitize OpenAI tracing export payloads (#2896)
### Summary

Updates the OpenAI tracing exporter to align usage metadata with the
trace ingest payload shape.

For the default OpenAI tracing endpoint, usage metadata is now only
included on generation spans, where it is normalized to the supported
token-count shape. Other tracing endpoints continue to receive the raw
SDK payload.

Adds regression coverage for OpenAI endpoint sanitization and custom
endpoint behavior.

### Test plan

- `make format`
- `make lint`
- `make sync && make typecheck`
- `uv run pytest
tests/test_openai_responses.py::test_get_response_span_exports_usage
tests/test_trace_processor.py` (46 passed)
- Manual tracing repro: `Runner.run(...)` completed, `flush_traces()`
completed, and no tracing client errors were emitted.
- `make tests` reached 3858 passed, 10 failed locally in sandbox tests
because `sandbox-exec` returned `sandbox_apply: Operation not
permitted`.

### Issue number

N/A

### Checks

- [x] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [x] I've run `make lint` and `make format`
- [ ] I've made sure tests pass
2026-04-15 12:19:30 -07:00
Kazuhiro Sera 0a100fb1e4 ci: add sandbox auto-label mapping (#2894) 2026-04-16 03:56:56 +09:00
Kazuhiro Sera fa049a26fb fix: stop streamed tool execution after known input guardrail tripwire (#2688) 2026-04-16 03:50:01 +09:00
Kazuhiro Sera 901348023d fix: #2873 preserve computer driver compatibility for modifier keys (#2877) 2026-04-16 03:43:15 +09:00
Kazuhiro Sera 83b3833382 fix #2151 shield server-managed handoffs from unsupported history rewrites (#2747) 2026-04-16 03:17:00 +09:00
github-actions[bot] 5d05d5d5d2 docs: update translated document pages (#2893) 2026-04-16 03:05:27 +09:00
HuxleyHu98 bd871cddb2 docs: clarify ToolContext availability in function-tool lifecycle hooks (#2687) 2026-04-16 02:55:53 +09:00
Kazuhiro Sera 489221155b docs: align translated sandbox nav and refresh generated refs (#2892) 2026-04-16 02:48:49 +09:00
github-actions[bot] e3366670ad docs: update translated document pages (#2891) 2026-04-16 02:25:27 +09:00
github-actions[bot] a7ccef4c6a Release 0.14.0 (#2890) 2026-04-16 02:09:57 +09:00
Steve Coffey 2d665c9a67 Sandbox Agents (#2889)
### Sandbox Agents

This release adds **Sandbox Agents**, a beta SDK surface for running
agents with a persistent, isolated workspace. Sandbox agents keep the
normal `Agent` and `Runner` flow, but add workspace manifests,
sandbox-native capabilities, sandbox clients, snapshots, and resume
support so agents can work over real files, run commands, edit
repositories, generate artifacts, and continue work across runs.

Key pieces:

- `SandboxAgent`: an `Agent` with sandbox defaults such as
`default_manifest`, sandbox instructions, capabilities, and `run_as`.
- `Manifest`: a fresh-workspace contract for files, directories, local
files, local directories, Git repos, environment, users, groups, and
mounts.
- `SandboxRunConfig`: per-run sandbox wiring for client creation, live
session injection, serialized session resume, manifest overrides,
snapshots, and materialization concurrency limits.
- Built-in capabilities for shell access, filesystem editing and image
inspection, skills, memory, and compaction.
- Workspace snapshots and serialized sandbox session state for
reconnecting to existing work or seeding a fresh sandbox from saved
contents.

### Sandbox clients and hosted providers

Sandbox agents now support local, containerized, and hosted execution
backends:

- `UnixLocalSandboxClient` for fast local development.
- `DockerSandboxClient` for container isolation and image parity.
- Hosted sandbox clients for Blaxel, Cloudflare, Daytona, E2B, Modal,
Runloop, and Vercel through optional extras.

The release also adds provider-specific examples and mount strategies
for common storage backends, including S3, Cloudflare R2, Google Cloud
Storage, Azure Blob Storage, and S3 Files where supported by the
selected backend.

### Sandbox memory

Adds a sandbox memory capability that lets future sandbox-agent runs
learn from prior runs. Memory stores extracted lessons in the sandbox
workspace, injects a concise summary into later runs, and uses
progressive disclosure so agents can search deeper rollout summaries
only when useful.

Memory supports:

- Read-only or generate-only modes.
- Live updates when the agent discovers stale memory.
- Multi-turn grouping through `conversation_id`, SDK `Session`,
`RunConfig.group_id`, or generated run IDs.
- Separate memory layouts for isolating memory across agents or
workflows.
- S3-backed examples for persisted memory across runs.

### Workspace mounts, snapshots, and resume

This release adds a full workspace entry and mount model for sandbox
sessions:

- Local files and directories.
- Synthetic files and directories.
- Git repository entries.
- Remote storage mounts for S3, R2, GCS, Azure Blob Storage, and S3
Files.
- Provider-specific mount strategies across Docker, Modal, Cloudflare,
Blaxel, Daytona, E2B, and Runloop.
- Portable snapshots with path normalization, symlink preservation,
mount-safe snapshotting, and remote snapshot support.
- Resume paths through runner-managed `RunState`, explicit
`SandboxSessionState`, or saved snapshots.

### Examples and tutorials

Adds a large `examples/sandbox/` suite covering:

- Local Unix and Docker sandbox runners.
- Docker mount smoke tests for S3, GCS, Azure Blob Storage, and S3
Files.
- Sandbox coding tasks with skills.
- Sandbox agents as tools and handoff patterns.
- Memory examples, including multi-agent/multi-turn memory and S3-backed
memory.
- Tax-prep and healthcare-support workflows.
- Dataroom QA and metric extraction tutorials.
- Repository code review tutorial.
- Vision website clone tutorial.
- Provider examples for Blaxel, Cloudflare, Daytona, E2B, Modal,
Runloop, Temporal, and Vercel.

### Runtime, tracing, and model plumbing

The release includes the runtime plumbing needed to make sandbox agents
work naturally inside the existing SDK:

- Runner-managed sandbox preparation, capability binding, session
lifecycle, state serialization, and resume behavior.
- Sandbox-aware `RunState` serialization.
- Unified sandbox tracing with SDK spans.
- Token usage on tracing spans.
- Runner-managed prompt cache key defaults.
- OpenAI agent registration and harness ID configuration.
- Safer redaction of sensitive MCP tool outputs when sensitive tracing
is disabled.
- Additional OpenAI client/model utilities and Chat Completions
coverage.


## Documentation & Other Changes

- docs: add Asqav to external tracing processors list.
- docs: update translated document pages.

Co-authored-by: Abdulrahman Alfozan <alfozan@openai.com>
Co-authored-by: Aditya Singh <60082699+adityasingh2400@users.noreply.github.com>
Co-authored-by: Andi Liu <andi@openai.com>
Co-authored-by: Aron <263346377+aron-cf@users.noreply.github.com>
Co-authored-by: ashwinnathan-openai <ashwinnathan@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: cploujoux <cploujoux@blaxel.ai>
Co-authored-by: elainegan-openai <168589666+elainegan-openai@users.noreply.github.com>
Co-authored-by: Elias Freider <freider@users.noreply.github.com>
Co-authored-by: Erik Dunteman <erik@erikds-macbook-air.local>
Co-authored-by: Jason Liu <jasonliu@openai.com>
Co-authored-by: Jason Steving <32336750+jasonsteving99@users.noreply.github.com>
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
Co-authored-by: Lovre Pešut <lovre.pesut@gmail.com>
Co-authored-by: Lucas Wang <lucas_wang@lucas-futures.com>
Co-authored-by: Matt Brockman <matt.brockman@e2b.dev>
Co-authored-by: Mish Ushakov <mishushakov@users.noreply.github.com>
Co-authored-by: Naresh <ghostwriternr@gmail.com>
Co-authored-by: nicholasclark-openai <nicholasclark@openai.com>
Co-authored-by: qiyaoq-oai <qiyaoq@openai.com>
Co-authored-by: Scott Trinh <scott@scotttrinh.com>
Co-authored-by: tode-rl <tony@runloop.ai>
Co-authored-by: Wendy Jiao <wendyjiao@openai.com>
2026-04-15 10:00:40 -07:00
github-actions[bot] 86739b1a0f docs: update translated document pages (#2870) 2026-04-10 07:29:44 +09:00
João André Marques 111cbf12ba docs: add Asqav to external tracing processors list (#2859)
Co-authored-by: Kazuhiro Sera <seratch@openai.com>
2026-04-09 22:25:50 +00:00
github-actions[bot] bfc8c6355f Release 0.13.6 (#2861) 2026-04-09 13:09:37 +09:00
Kazuhiro Sera 690079e2b9 fix: #2863 lazy-load SQLiteSession exports (#2864) 2026-04-09 12:13:48 +09:00
Kazuhiro Sera fb67680fae fix: #2856 stop recursive trace preview truncation (#2860) 2026-04-08 20:08:33 +09:00
Kazuhiro Sera c06cd45004 fix: harden SQLAlchemySession against transient SQLite locks (#2854) 2026-04-08 08:21:37 +09:00
github-actions[bot] aeb653e562 docs: update translated document pages (#2853) 2026-04-08 06:56:00 +09:00
m1lestones 0386210b3b docs(tracing): add HoneyHive to tracing integrations list (#2851) 2026-04-07 21:51:20 +00:00
github-actions[bot] fa508992ed docs: update translated document pages (#2847) 2026-04-06 13:32:35 +09:00
Kazuhiro Sera e1d861ca50 docs: updates for #2844 changes (#2845) 2026-04-06 13:12:14 +09:00
github-actions[bot] b0ab25c2d6 Release 0.13.5 (#2821) 2026-04-06 13:10:33 +09:00
Kazuhiro Sera 7a3f6b70d1 feat: #2135 add public flush_traces API (#2844) 2026-04-04 12:19:50 +09:00
Kazuhiro Sera 6a89f1b564 fix: serialize SQLite session writes with shared file locks (#2843) 2026-04-04 12:19:29 +09:00
github-actions[bot] 76f419f795 docs: update translated document pages (#2828) 2026-04-02 15:05:13 +09:00
祝子祺 fe9e70fd4d fix: #2823 AnyLLM reasoning extraction for iterable vLLM/any-llm Reasoning objects (#2822) 2026-04-02 14:50:28 +09:00
Abdullah Faheem f75a40ebe2 docs: sync examples.md with current examples directory (#2827) 2026-04-02 14:49:40 +09:00
dependabot[bot] c9400550a7 chore(deps): bump astral-sh/setup-uv from 7.3.1 to 8.0.0 (#2820) 2026-04-01 14:14:49 +09:00
dependabot[bot] 70939dc73d chore(deps): bump openai/codex-action from 1.4 to 1.6 (#2819) 2026-04-01 14:14:36 +09:00
Kazuhiro Sera 976bccedc4 feat: #2807 support callable approval policies for local MCP servers (#2818) 2026-04-01 14:14:01 +09:00
github-actions[bot] 051c2ea388 Release 0.13.4 (#2815) 2026-04-01 11:37:18 +09:00
Kazuhiro Sera 40aada1a8b fix: #2806 sanitize AnyLLM responses replay input before validation (#2813) 2026-03-31 19:35:22 +09:00
Kazuhiro Sera 5e0e6d26f0 fix: map extensions changes to the feature:extensions label (#2814) 2026-03-31 10:30:19 +00:00
github-actions[bot] d86c2e27d9 Release 0.13.3 (#2801) 2026-03-31 13:32:23 +09:00
Kazuhiro Sera 9f5575ada4 fix: #2798 avoid stale hydrated input ids in server conversation tracker (#2800) 2026-03-28 11:06:03 +09:00
Kazuhiro Sera a7b4851e69 fix: #2797 accept raw image_url content parts on chat completions input (#2799) 2026-03-28 11:02:39 +09:00
Kazuhiro Sera 9ed6dadb41 chore: add Codex Stop hook for targeted Ruff tidy (#2795) 2026-03-27 21:04:49 +09:00
Kazuhiro Sera ce0d7923b8 docs: tweak for #2792 changes 2026-03-27 16:58:52 +09:00
github-actions[bot] a4db3e5519 docs: update translated document pages (#2793) 2026-03-27 16:56:48 +09:00
Muttaqi110 149f5ce631 docs: add non-OpenAI provider code example (#2792) 2026-03-27 07:41:03 +00:00
github-actions[bot] dddbce144e Release 0.13.2 (#2774) 2026-03-27 08:54:52 +09:00
Kazuhiro Sera c5e132142c fix: #2783 depend on griffelib directly for docstring parsing (#2791) 2026-03-27 08:18:04 +09:00
Kazuhiro Sera 7fea1a549e fix: improve a flaky test for realtime module (#2787) 2026-03-26 12:54:45 +00:00
ふぁー c52d25f4f9 feat: #2785 add external_web_access to WebSearchTool (#2786) 2026-03-26 21:40:18 +09:00
Kazuhiro Sera 570b114770 docs: update readme 2026-03-26 20:52:17 +09:00
Kazuhiro Sera c2f6690ff2 fix: #2776 keep private tool metadata out of persisted session items (#2781) 2026-03-26 20:09:37 +09:00
Kazuhiro Sera 9a96d9e787 fix: #2778 keep LiteLLM reasoning_effort portable across providers (#2782) 2026-03-26 15:05:22 +09:00
Kazuhiro Sera 67fa4d89a5 chore: make sync 2026-03-26 14:26:22 +09:00
Kazuhiro Sera 8fdb45da69 fix: update default reasoning effort for newer models (#2773) 2026-03-25 22:10:15 +09:00
Lucas Wang abd5cef032 fix: pin liteLLM upper bound to 1.82.6 to mitigate supply chain attack (#2772) 2026-03-25 22:09:58 +09:00
github-actions[bot] 7dc7fa2be1 docs: update translated document pages (#2771) 2026-03-25 16:55:39 +09:00
Kazuhiro Sera 13f4a7405e docs: update pages to add any-llm adapter (#2715) 2026-03-25 16:46:21 +09:00
github-actions[bot] 0a5b8c9ce5 Release 0.13.1 (#2768) 2026-03-25 16:37:26 +09:00
Kazuhiro Sera 881f402aa2 fix: harden example auto-runs against PATH and port conflicts (#2770) 2026-03-25 16:31:44 +09:00
elainegan-openai 90884968b3 fix: optionize initialized notification tolerance (#2765) 2026-03-25 14:35:54 +09:00
elainegan-openai 687e974046 fix: handle cancelled single function tools as tool failures (#2762) 2026-03-25 14:17:20 +09:00
Kazuhiro Sera b8355b2781 docs: add missing ref files 2026-03-25 11:43:32 +09:00
Kazuhiro Sera 1c0ff599c8 feat: add any-llm model support with responses-compatible routing (#2706) 2026-03-25 11:38:43 +09:00
Kazuhiro Sera 8e1915ef60 fix: preserve static MCP meta in converted function tools (#2769) 2026-03-25 09:23:26 +09:00
Kazuhiro Sera 0cc4805c00 fix: #2760 wait for realtime response.done before follow-up response.create (#2763) 2026-03-25 07:59:29 +09:00
959 changed files with 153790 additions and 11254 deletions
+40
View File
@@ -0,0 +1,40 @@
# SDK Maintainer References
This directory captures long-lived implementation contracts of the OpenAI Agents Python SDK that are not replaceable by OpenAI API or platform facts from the Developer Docs MCP. The repo's `docs/` remain an SDK-specific behavioral contract; these references distill the ownership, compatibility, ordering, and failure semantics that maintainers need to preserve that contract.
## Usage
Read the reference map before changing or reviewing an affected runtime boundary, then open only the files relevant to that boundary. During issue and PR review, treat this directory as read-only background: use it to identify expected invariants, adjacent surfaces, and regression risks, but verify the current claim against the remote issue or PR, current code, tests, docs, release boundary, and focused runtime evidence. Do not edit references as a side effect of a review or treat them as proof of current issue status, PR behavior, or repository readiness.
When implementation or dedicated repository-maintenance work establishes a reusable invariant that remains valid beyond one issue or PR, update the narrowest owning reference separately. Preserve the generalized contract, not the case history or decision outcome that revealed it.
## Inclusion Criteria
Add or retain a reference when the knowledge is SDK-specific, stable across multiple releases, easy to violate from one local code path, and expensive to reconstruct from source, tests, and repo docs during every review. Treat `docs/` as the SDK's user-facing behavioral contract; use these references to preserve the implementation constraints behind that contract. Prefer invariants and ownership rules over summaries of individual issues, PRs, or recent fixes.
Do not store current issue or PR status, generic maintainer-review workflow, release notes, OpenAI API or platform behavior available through `$openai-knowledge`, or one-off implementation details in this directory. Put review methodology under `.agents/skills/`, released migration notes in `docs/release.md`, and API or platform facts behind `$openai-knowledge`.
## Reference Map
| Reference | Read before changing or reviewing |
|---|---|
| [Agent definition and run context](agent-definition-and-run-context.md) | Agent fields, cloning, dynamic instructions, enabled tools or handoffs, context wrappers, usage, or public agent identity |
| [Runner lifecycle](runner-lifecycle.md) | Turn accounting, guardrails, handoffs, interruptions, cancellation, or streaming parity |
| [Run item lifecycle](run-item-lifecycle.md) | Model output processing, new item types, stream events, replay conversion, session persistence, or RunState serialization |
| [Function and output schema](function-and-output-schema.md) | Function-tool signatures and metadata, strict JSON schema conversion, or structured output types |
| [Conversation state ownership](conversation-state-ownership.md) | Sessions versus server-managed continuation, input deltas, retries, compaction, or conversation resume |
| [Session persistence](session-persistence.md) | Session input callbacks, per-turn saves, retry rewind, atomicity, or compaction replacement |
| [RunState schema and resume boundary](runstate-schema.md) | Serialized state, schema versions, approvals, agent identity, or durable resume data |
| [Tool identity and routing](tool-identity.md) | Tool names, namespaces, lookup, approvals, MCP naming, handoffs, or call IDs |
| [Tool execution lifecycle](tool-execution-lifecycle.md) | Function-tool planning, approvals, guardrails, concurrency, cancellation, timeouts, or failure conversion |
| [Local MCP server lifecycle](local-mcp-server-lifecycle.md) | Local MCP connection ownership, manager state, request serialization, caching, filtering, retries, or cleanup |
| [Model and provider boundaries](model-provider-boundaries.md) | Model resolution, provider adapters, feature capability, request conversion, terminal events, or retries |
| [Tracing lifecycle](tracing-lifecycle.md) | Trace and span context, processors, export, flush, shutdown, resume, or sensitive data |
| [Realtime session lifecycle](realtime-session-lifecycle.md) | Realtime listeners, connections, background tasks, handoffs, event iteration, or cleanup |
| [Realtime tracing architecture](realtime-tracing.md) | Realtime API server traces versus Agents SDK client traces |
| [Voice pipeline lifecycle](voice-pipeline-lifecycle.md) | VoicePipeline STT/workflow/TTS ownership, event and audio ordering, stream cleanup, PCM framing, or tracing |
| [Sandbox runtime boundary](sandbox-runtime-boundary.md) | Sandbox session ownership, preparation, resume state, manifests, materialization, or cleanup |
## Maintenance Rules
Keep each rule in the narrowest reference that owns it. Cross-link instead of copying detailed rules between files. Describe current architecture and compatibility boundaries, not the chronology of how a bug was found. Use source paths and durable public contracts as anchors, and remove or rewrite guidance when ownership moves.
@@ -0,0 +1,57 @@
# Agent Definition and Run Context
Use this reference for changes to public `Agent` fields, cloning, dynamic instructions, enabled tools or handoffs, output schemas, `RunContextWrapper`, `ToolContext`, usage aggregation, or the distinction between a public agent and an internal prepared clone.
## Public Definition and Cloning
- Exported `Agent` and `AgentBase` dataclass field order is a positional compatibility boundary. Append optional fields where possible and test old positional construction when the order changes.
- `Agent.__post_init__()` is the eager boundary for invalid field categories such as names, tools, handoffs, hooks, model settings, output types, and tool-use behavior. Dynamic callbacks are validated when invoked because their result depends on the current run.
- `Agent.clone()` uses `dataclasses.replace()` and is shallow. Mutable fields and contained tool, handoff, hook, and provider objects remain shared unless the caller explicitly supplies replacements.
- When `clone(model=...)` replaces a model whose settings still equal the old model's implicit defaults, recompute the new model's implicit defaults. Preserve explicitly customized `model_settings` instead of silently resetting them.
## Per-Turn Resolution
- Resolve dynamic instructions with the current context and public agent for each model turn. Enforce the documented two-argument callable shape and await async results.
- Evaluate callable `FunctionTool.is_enabled` and `Handoff.is_enabled` against the current run context. Do not cache a prior run's enabled set on the reusable agent.
- Use one resolved tool and handoff view for model exposure, reserved-name and collision checks, local dispatch, tracing, and Realtime session updates. Re-resolving independently at those surfaces can expose one set and execute another.
- An internal prepared agent may add bound tools, instructions, or sampling settings, but hooks, `ToolContext.agent`, handoff callbacks, and public results should identify the public agent unless an internal identity is explicitly part of the contract.
- The effective output schema belongs to the agent and model call that produced the candidate output. A handoff can change the final output type, so do not assume the starting agent's schema when parsing or typing the final result.
## Context Ownership
- Every agent, tool, handoff, guardrail, and lifecycle hook in one run must agree on the same application context type. The context object is local runtime state and is never added to model input automatically.
- A normal `ToolContext.from_agent_context()` shares the underlying application object, usage accumulator, and approval mapping with its parent while adding call-scoped fields such as call ID, namespace, arguments, and conversation history.
- Nested `Agent.as_tool()` execution has a separate run loop, approval scope, and resumable tool state. On the normal function-tool path it still shares the application object and usage accumulator, while `tool_input` belongs to the nested wrapper and must not overwrite the parent's scoped value.
- Sharing the application object is not the same as sharing every wrapper field. Add explicit application-level isolation when nested mutation is unsafe, and do not reuse parent approval decisions for nested calls merely because the tool name or call ID looks similar.
- Context serialization is a separate durability decision. Read [RunState schema and resume boundary](runstate-schema.md) before persisting custom context objects, approvals, usage, or nested tool input.
## Usage Accounting
- `RunContextWrapper.usage` is the run-wide mutable accumulator. Add each model response exactly once across streaming, non-streaming, retries, nested runs, handoffs, and resume paths.
- Preserve authoritative `request_usage_entries` when combining usage. Do not synthesize a second per-request entry from aggregate totals when the provider or retry layer already supplied request-level records.
- Retry accounting may include failed attempts with no token totals. Keep request count, aggregate tokens, request-level entries, and trace span usage internally consistent without inventing provider token data.
- Streamed usage remains incomplete until terminal chunks and the stream driver finish. Do not finalize billing, result summaries, or usage-bearing spans from the last visible text delta alone.
## Review Checklist
1. Test direct construction and clone behavior without mutating shared caller-owned objects.
2. Resolve dynamic instructions, tools, and handoffs through the same public agent and current context used for dispatch.
3. Verify handoff and internal prepared-agent paths expose the intended public identity and effective output schema.
4. Test nested agent tools for shared application state and isolated scoped metadata.
5. Compare aggregate and per-request usage after streaming, retries, handoffs, interruption resume, and nested runs.
## Sources
- `docs/agents.md`
- `docs/context.md`
- `docs/results.md`
- `src/agents/agent.py`
- `src/agents/run_context.py`
- `src/agents/tool_context.py`
- `src/agents/usage.py`
- `src/agents/run_internal/turn_preparation.py`
- `src/agents/run_internal/run_loop.py`
- `tests/test_agent_config.py`
- `tests/test_agent_clone_shallow_copy.py`
- `tests/test_agent_as_tool.py`
- `tests/test_usage.py`
@@ -0,0 +1,67 @@
# Conversation State Ownership
Use this reference for changes involving multi-turn input, sessions, `conversation_id`, `previous_response_id`, `auto_previous_response_id`, compaction, retries, `call_model_input_filter`, or `RunState` resume.
## Choose One Conversation Strategy
The state owner determines what the next model request should contain.
| Strategy | State owner | Next-turn input |
|---|---|---|
| Explicit replay with `result.to_input_list()` | Application | Replay-ready history plus the new turn |
| SDK session | Application storage plus the SDK | The same session plus the new turn |
| `conversation_id` | OpenAI Conversations API | The same conversation ID plus only the new turn |
| `previous_response_id` or `auto_previous_response_id` | OpenAI Responses API | The previous response ID plus only the new turn |
| `RunState` resume | Serialized Agents SDK run | Resume the same interrupted run; this is not a new conversation strategy |
In normal use, select one conversation strategy. Mixing client-managed replay or sessions with server-managed continuation can duplicate context unless the implementation explicitly reconciles both owners. Read [Session persistence](session-persistence.md) for the client-managed storage contract.
## Server-Managed Continuation
- `OpenAIServerConversationTracker` in `src/agents/run_internal/oai_conversation.py` owns delta calculation for `conversation_id`, `previous_response_id`, and `auto_previous_response_id`.
- Send only items that the server has not already acknowledged. Object identity is useful only within one process; resume and retry paths also require stable item IDs, tool call IDs, and content fingerprints.
- Update `previous_response_id` from the most recent response that actually has an ID. Do not erase a valid chain because an adjacent provider response lacks one.
- Session persistence cannot be combined with server-managed continuation. `validate_session_conversation_settings()` rejects a session with `conversation_id`, `previous_response_id`, or `auto_previous_response_id`; do not add a second history writer without defining reconciliation and dedupe semantics.
- Treat `conversation_id` and `previous_response_id` / `auto_previous_response_id` chaining as mutually exclusive state owners.
## Filters, Retries, and Resume
- `call_model_input_filter` runs on the prepared model payload. With server-managed continuation, that payload may already be a new-turn delta rather than full history.
- The filter must return `ModelInputData` with list input. Mark exactly the returned list as sent immediately before the request so nested preparation cannot add unsent items, rewind that tracking before retrying a failed request, and preserve it after success.
- Keep streaming and non-streaming tracker updates aligned. Both paths must preserve the same delta, retry, and response-ID semantics.
- Stateful retries require replay-safety evidence. Do not blindly resend a request that may already have advanced server state.
- `RunState` persists conversation identifiers and reconstructs tracker knowledge for resumed runs. Resume must not replay acknowledged input, lose unsent tool outputs, or increment the turn count without a model call.
- Conversation continuation carries context into a new turn. `RunState` resume continues a paused run. Do not substitute one mechanism for the other.
## Compaction
- `compaction_mode="previous_response_id"` depends on a usable stored response chain.
- `compaction_mode="input"` rebuilds from client-held items and is the fallback when the server chain is unavailable or `store=False` prevents later response lookup.
- Compaction must preserve the chosen state owner. Do not compact from local history and then also replay that history through server-managed continuation.
## Handoffs
- Server-managed conversations send deltas, so handoff input filters are not supported. `Handoff.input_filter` and `RunConfig.handoff_input_filter` should raise instead of rewriting a history the server already owns.
- `nest_handoff_history` is a client-history transformation. When server-managed continuation is active, disable it with a warning and continue with delta-only input.
- Keep generated items and session items distinct during handoff processing. The next model input may be filtered, but session history needs the full unfiltered item sequence when client-managed sessions are active.
## Review Checklist
1. Name the state owner before changing request construction.
2. Specify whether the model receives full history or a delta on every affected path.
3. Verify first turn, follow-up turn, retry, interruption, serialized resume, and streaming behavior.
4. Test tool calls and outputs separately; call IDs and output fingerprints have different dedupe roles.
5. Confirm that filtering, compaction, and session persistence do not introduce a second source of truth.
## Sources
- [OpenAI conversation state guide](https://developers.openai.com/api/docs/guides/conversation-state)
- [OpenAI running agents guide](https://developers.openai.com/api/docs/guides/agents/running-agents#choose-one-conversation-strategy)
- `src/agents/run_internal/oai_conversation.py`
- `src/agents/run_internal/run_loop.py`
- `src/agents/run_internal/session_persistence.py`
- `src/agents/run_state.py`
- `docs/running_agents.md`
- `docs/sessions/index.md`
Recheck the official API reference with `$openai-knowledge` before changing server-managed continuation behavior.
@@ -0,0 +1,50 @@
# Function and Output Schema
Use this reference for changes to function-tool signature inspection, parameter metadata, strict JSON schema conversion, tool argument reconstruction, or structured agent output schemas.
Schema behavior is a compatibility boundary shared by Python callables, Pydantic, model providers, and runtime validation. Keep schema generation and invocation aligned rather than fixing one representation in isolation.
## Function Schema Ownership
- Explicit decorator arguments for a function name or description override values inferred from the callable and its docstring.
- Parameter descriptions from parsed docstrings take precedence over description strings carried by `Annotated`. Preserve `Field` constraints, aliases, and defaults when merging `Annotated` metadata.
- A run context parameter is special only in the first parameter position. Exclude it from the model-visible schema while still supplying it during invocation; do not silently treat later context-typed parameters as injected context.
- Keep the inspected signature, generated Pydantic model, JSON schema, and `to_call_args()` reconstruction consistent. Cover positional-only parameters, keyword-only parameters, `*args`, and `**kwargs` when changing this path.
- Reject unsupported callable shapes or invalid schemas when the tool is constructed so failures do not depend on whether a particular model later selects the tool.
## Strict JSON Schema Conversion
- Strict conversion closes object schemas with `additionalProperties: false` and marks their declared properties required. Reject an explicit `additionalProperties: true` instead of silently changing its meaning.
- Preserve the meaning of unions, intersections, definitions, and references. Normalize `oneOf` where required, process `allOf`, retain chained references, and merge a referenced schema with sibling keys without discarding the siblings.
- Remove defaults that only encode Python `None`; a nullable type must remain represented by its type schema rather than by an unsupported default.
- `ensure_strict_json_schema()` may mutate a non-empty input dictionary. Copy caller-owned schemas at public boundaries before conversion. Empty-schema conversion must return a fresh object rather than shared mutable state.
- Keep strictness explicit. If a tool or output schema opts out of strict mode, preserve that choice through provider conversion instead of partially applying strict normalization.
## Structured Output Schemas
- Plain `str` output and no declared output type use the plain-text path. Pydantic models and dictionary-shaped outputs expose their object schema directly; other Python types use the SDK's wrapper object with the `response` key.
- Keep generated output names stable and descriptive for nested generics, unions, and `Literal` types. These names are observable in provider requests and diagnostics.
- Parse model output as JSON and validate it through the output type adapter. Convert JSON or validation failures to the SDK's model-behavior error boundary rather than leaking provider- or Pydantic-specific exceptions.
- Streaming and non-streaming adapters must carry the same schema, strictness flag, wrapper behavior, and validation result.
## Review Checklist
1. Test precedence among explicit metadata, docstrings, `Annotated`, and `Field` values.
2. Test invocation reconstruction for positional-only, keyword-only, variadic, and context-bearing callables.
3. Test nested objects, unions, intersections, sibling and chained references, nullable fields, and caller-owned schema mutation.
4. Test plain text, direct object output, wrapped scalar or generic output, invalid JSON, and validation failure.
5. Verify every provider adapter receives the same normalized schema and strictness decision.
## Sources
- `src/agents/function_schema.py`
- `src/agents/strict_schema.py`
- `src/agents/tool.py`
- `src/agents/agent_output.py`
- `src/agents/models/`
- `tests/test_function_schema.py`
- `tests/test_function_tool_decorator.py`
- `tests/test_strict_schema.py`
- `tests/test_strict_schema_oneof.py`
- `tests/test_output_tool.py`
- `tests/models/`
@@ -0,0 +1,56 @@
# Local MCP Server Lifecycle
Use this reference for changes to Python-managed MCP servers, `MCPServerManager`, client-session request ordering, tool caching or filtering, local MCP retries, cancellation, or cleanup. Hosted MCP is a provider tool and follows the OpenAI API contract; use `$openai-knowledge` for that protocol surface. Read [Tool identity and routing](tool-identity.md) for server-prefixed names and [Tool execution lifecycle](tool-execution-lifecycle.md) for approval and invocation behavior after an MCP tool is converted to a `FunctionTool`.
## Connection Ownership and Task Affinity
- A local `MCPServer` owns its transport, `ClientSession`, and `AsyncExitStack` from `connect()` through `cleanup()`. Partial connection failure still requires closing every context already entered.
- Some MCP transports use AnyIO cancel scopes that require connection and cleanup in the same task. Do not wrap either operation in a helper that silently creates another task.
- `MCPServerManager` preserves task affinity in sequential mode and uses one long-lived worker task per server in parallel mode. Timeouts must run inside that owning task; on Python versions without `asyncio.timeout()`, cancel the current worker task and translate only timer-originated cancellation to `TimeoutError`.
- Cleanup runs servers in reverse order and continues across ordinary cleanup failures. Cancellation suppression is an explicit manager policy; do not accidentally convert unrelated `BaseException` failures into recoverable connection errors.
- Server cleanup must clear session and transport-visible state even when exit-stack cleanup raises, so the same server object can reconnect without exposing stale session handles or workers.
## Manager State
- Keep configured servers, connected servers, failed servers, active servers, and per-server errors as distinct views. `active_servers` is the agent-facing list; with `drop_failed_servers=True` it excludes failed connections while preserving configured order.
- Non-strict connection records failures and continues with the connected subset. Strict connection cleans up work started by the failed attempt and restores the previous coherent active state before raising.
- `reconnect(failed_only=True)` retries the deduplicated failed set without disturbing healthy connections. A full reconnect cleans up all servers first and rebuilds manager state.
- Parallel connection still needs deterministic per-server state and complete cleanup after cancellation or one hard failure. Do not let completion order decide `active_servers`, `failed_servers`, or which workers remain registered.
## Shared Session Requests and Retries
- Streamable HTTP can require requests on one shared MCP session to be serialized. The same lock must cover tool calls, tool listing, prompts, and resource operations that share that session; serializing only `call_tool()` still permits sibling cancellation and protocol races.
- Preserve outer cancellation. A cancelled shared request may qualify for an isolated-session retry only when the transport identifies it as an inner or transient session failure and retry budget remains.
- Isolated-session retries are transport-specific recovery. Count isolated session setup and execution against the same retry budget, retry only the supported transient failure shapes, and never replay mixed exception groups or ordinary 4xx failures as if they were safe.
- Generic `list_tools()` and `call_tool()` retries use the configured attempt count and backoff. Validate required arguments locally before starting retries so deterministic input errors never reach the server or consume retry budget.
- MCP tool failure conversion follows the effective server or agent `failure_error_function`. Explicit `None` means propagate; cancellation of the parent run must not become model-visible tool failure output.
## Tool Discovery, Cache, and Filtering
- The unfiltered server tool list is the cacheable value. Apply static or dynamic filters to a copy for each requesting agent and run context; never let one request's filtered or merged metadata mutate the shared cache.
- `cache_tools_list=True` assumes server schemas are stable until `invalidate_tools_cache()` marks them dirty. Connection or filter changes must not accidentally make a stale filtered list authoritative.
- Dynamic filters require both `run_context` and agent. A filter exception excludes that tool and logs the failure rather than exposing it by default.
- Schema conversion to strict form is best effort and must not mutate the MCP server's original input schema. If strict conversion fails, preserve the original schema and keep metadata isolated per converted `FunctionTool`.
- Tool list collision errors, prefixed-name generation, and approval policy validation must be deterministic regardless of server response or connection completion order.
## Review Checklist
1. Identify the task that owns connect, every request, timeout cancellation, and cleanup for each transport.
2. Test partial connect failure, strict and non-strict manager modes, reconnect, repeated cleanup, and manager cancellation.
3. Test overlapping tool, prompt, and resource requests when shared-session serialization is enabled.
4. Prove retries preserve outer cancellation, consume one budget, and do not replay deterministic or unsupported failures.
5. Test cache invalidation, context-dependent filters, schema immutability, duplicate names, and reconnect with the public runner path.
## Sources
- `docs/mcp.md`
- `src/agents/mcp/server.py`
- `src/agents/mcp/manager.py`
- `src/agents/mcp/util.py`
- `tests/mcp/test_mcp_server_manager.py`
- `tests/mcp/test_connect_disconnect.py`
- `tests/mcp/test_client_session_retries.py`
- `tests/mcp/test_caching.py`
- `tests/mcp/test_tool_filtering.py`
- `tests/mcp/test_server_errors.py`
- `tests/mcp/test_runner_calls_mcp.py`
@@ -0,0 +1,75 @@
# Model and Provider Boundaries
Use this reference for changes to model resolution, `ModelSettings`, provider adapters, Responses versus Chat Completions behavior, request conversion, streaming terminal events, transport reuse, or model retries.
## Core Boundary
The run loop depends on the `Model` interface, not on one provider's request or response schema.
- `Model.get_response()` returns a normalized `ModelResponse`.
- `Model.stream_response()` yields normalized response stream events while preserving provider payloads needed by public raw-event consumers.
- `ModelProvider.get_model()` resolves names to model implementations and owns provider-level caches or connections.
- `Model.close()` and `ModelProvider.aclose()` release persistent transport resources when an implementation owns them.
Provider adapters own request construction, provider feature validation, terminal event interpretation, usage conversion, and translation into SDK item shapes. Keep provider-specific branching out of the core run loop unless it represents a shared SDK contract.
## Model and Settings Resolution
- An explicit `RunConfig.model` overrides the agent model. A model instance is used directly; a model name is resolved through the configured `ModelProvider`.
- Implicit default settings must follow the resolved model name, including when a run-level model name replaces the agent default.
- Resolve agent settings with run-level settings by overlaying non-`None` values. Preserve the documented merge behavior for structured fields such as `extra_args` and retry settings.
- Do not pass provider request extras into tracing by default. `ModelSettings.to_traceable_dict()` is the boundary for settings considered safe and meaningful in traces.
## Capability Ownership
Do not infer that a feature available in one adapter is supported by every `Model` implementation.
- Responses-specific features include server-managed response chaining, conversation-aware request fields, tool namespaces, deferred tool loading, tool search, response includes, compaction, and Responses websocket transport.
- Chat Completions generally requires client-managed replay and adapter conversion of Responses-compatible SDK items. Unsupported server-state or tool features should be rejected or explicitly ignored according to the adapter's documented validation mode.
- Realtime has its own session protocol, event model, and server tracing. Do not route Realtime behavior through the standard Responses or Chat Completions assumptions.
- Third-party model adapters may preserve only the shared `Model` contract. New provider-specific fields need an explicit conversion and fallback policy.
Validate capabilities at the adapter boundary where the resolved model and complete request are known. Avoid public flags that appear accepted by the SDK but are silently dropped before the provider request.
## Provider Data and Terminal Semantics
- Preserve provider-supplied string IDs, request IDs, usage, and opaque provider data when the public SDK contract exposes them.
- Normalize provider objects and mapping payloads without relying on truthiness for valid empty or zero values.
- A transport stream ending is not automatically a successful model response. Responses `failed` and `incomplete` terminals, explicit error events, and a missing terminal payload must produce the documented failure behavior in both HTTP and websocket paths.
- Keep semantically equivalent HTTP, websocket, streaming, and non-streaming paths aligned on final `ModelResponse`, errors, request IDs, and usage.
## Transport Resource Ownership
- Persistent Responses websocket models are loop-bound resources. Cache reusable websocket model instances by running event loop and model name; do not share one connection or `asyncio.Lock` across loops.
- Use weak loop ownership so an unused cache does not keep a closed event loop alive. When a live connection itself pins a closed loop, prune it with synchronous abort and state clearing rather than awaiting work on that closed loop.
- A provider that caches persistent models must make `aclose()` close every unique cached model and clear its caches. Close on a still-running owner loop when possible; do not drive an inactive foreign loop inside `asyncio.to_thread()`.
- A model used without a running loop cannot safely join the loop-scoped websocket cache. Preserve the non-reuse fallback rather than attaching it to an arbitrary global loop.
- Connection reuse ends after protocol errors, pre-terminal disconnects, cancellation that invalidates framing, or explicit close. Clear connection and loop-bound lock state together so a later request cannot reuse half-closed transport state.
## Retry and Replay Safety
- Provider retry advice can describe retryability, delay, and replay safety; the runner must not replace provider-specific evidence with a generic status-code assumption.
- Requests that use server-managed conversation state or may have produced side effects are not automatically replay-safe. A retry policy must account for whether the provider could have accepted the previous attempt.
- Retry conversion and error handlers must preserve the original exception semantics and avoid leaking sensitive request payloads through chaining, logs, traces, or provider error objects.
## Review Checklist
1. Identify which adapter owns the feature and how unsupported adapters behave.
2. Verify model and implicit-settings resolution when run config overrides the agent.
3. Compare HTTP/websocket and streaming/non-streaming terminal behavior when applicable.
4. Preserve request IDs, usage, provider data, and error semantics through normalization.
5. Prove retries are safe for the request's state ownership and side effects.
6. Test transport reuse, cross-loop access, closed-loop pruning, and provider shutdown when persistent connections are involved.
## Sources
- `src/agents/models/interface.py`
- `src/agents/model_settings.py`
- `src/agents/run_internal/turn_preparation.py`
- `src/agents/models/openai_responses.py`
- `src/agents/models/openai_chatcompletions.py`
- `src/agents/models/multi_provider.py`
- `src/agents/models/_response_terminal.py`
- `src/agents/run_internal/model_retry.py`
- `tests/models/`
- `tests/test_config.py`
@@ -0,0 +1,73 @@
# Realtime Session Lifecycle
Use this reference for `RealtimeSession` changes involving entry, exit, listeners, connections, background tasks, approvals, handoffs, event iteration, tracing context, or cleanup.
## Resource Ownership
Treat the session as the owner of these resources once they are acquired:
| Resource | Acquisition | Required release or terminal state |
|---|---|---|
| Model listener | `add_listener()` during entry | `remove_listener()` |
| Model connection | `model.connect()` | `model.close()` |
| Event iterators | Waiting on the event queue | Wake or terminate every waiter on close |
| Guardrail tasks | Created during output processing | Complete, or cancel and account for completion |
| Tool-call tasks | Created when `async_tool_calls=True` | Complete, or cancel and account for completion |
| Pending approvals and outputs | Added during tool execution | Resolve, retain for retry, or clear during terminal cleanup |
| Agent and model settings | Updated on handoff or `update_agent()` | Keep runtime state and model configuration aligned |
Do not add a new side effect before a failure point without defining who releases it.
## Entry and Exit
- Python does not call `__aexit__` when `__aenter__` raises. Any listener, connection, task, tracing scope, or other resource acquired before the exception needs explicit failure cleanup.
- Keep construction free of external side effects. Acquire listeners and connections during entry where failures can be handled coherently.
- `close()` and internal cleanup must be idempotent. Repeated close paths should still wake event iterators without closing the model twice.
- Mark the session closed only after the cleanup state is coherent. If model close fails, decide deliberately whether retry is possible and which resources remain owned.
## Async Task and Context Rules
- `asyncio` tasks inherit a snapshot of the creator's context. A background task cannot update the caller task's `ContextVar` state.
- A `ContextVar` token must be reset in the same context that created it. Never pass a token to a different task and assume cleanup can reset it safely.
- Shared session fields can be mutated by the listener path, tool-call tasks, `close()`, `update_agent()`, and handoff handling. Review ordering and races whenever one of those paths changes.
- Calling `task.cancel()` requests cancellation; it does not prove the task has finished its `finally` blocks or released resources. Await cancelled tasks when completion matters, or document and test why dropping them is safe.
- Background-task exceptions must reach a deterministic owner. They must not silently disappear or leave event consumers blocked.
## Agent Transitions
- Handoffs and the public `update_agent()` API are equivalent agent-transition surfaces. Keep their model settings, tool and handoff resolution, emitted events, and tracing metadata aligned unless a difference is intentional and documented.
- Resolve dynamic tools and enabled handoffs once per transition when possible, then reuse the exact resolved values for model settings and metadata.
- With concurrent tool calls, capture the agent snapshot associated with each call. Do not route a call through whichever agent happens to be current when the task eventually runs.
## Guardrails and Response Ordering
- Realtime output guardrails inspect accumulated transcript text at configured debounce thresholds, not each token and not a final `Runner` output object. They emit `guardrail_tripped` instead of raising a normal Runner tripwire exception.
- A tripped output guardrail marks the response interrupted before awaiting transport work, emits one trip event per response, forces response cancellation, and sends safe follow-up input naming the guardrail. Concurrent guardrail tasks must not interrupt or message the same response twice.
- Guardrail callbacks can run after audio has already been buffered or played. Consumers must treat `audio_interrupted` as the signal to stop local playback; text rejection alone cannot retract audio already delivered.
- An exception from one output guardrail is logged and skipped so it does not silently terminate the live session. Exceptions that escape the background guardrail task must become a `RealtimeError` event rather than disappearing.
- Realtime function-tool input guardrails follow the same optional pre-approval and mandatory post-approval ordering as standard function tools, but their rejection is returned through Realtime tool output and events.
- Follow-up `response.create` work triggered by tools, handoffs, or guardrails must respect the active response lifecycle. Wait for `response.done` or the model layer's equivalent gate before starting a conflicting response.
## Failure-Path Tests
Add focused tests for affected phases:
1. Instruction, tool, or handoff resolution fails during entry.
2. Model connection fails after listener registration.
3. A background tool or guardrail task raises or is cancelled.
4. Cleanup runs while event iterators are waiting.
5. `close()` is called repeatedly or from another task.
6. A handoff or `update_agent()` fails partway through model-settings application.
7. Tool output sending fails after local execution and must be retried without running the tool twice.
8. Concurrent guardrail tasks trip once, cancel playback, and do not overlap follow-up responses.
Verify lifecycle changes with the real public path where feasible; helper-only tests are insufficient when task ownership or context propagation determines the result.
## Sources
- `src/agents/realtime/session.py`
- `src/agents/realtime/model.py`
- `src/agents/realtime/openai_realtime.py`
- `tests/realtime/test_session.py`
- `tests/realtime/test_session_exceptions.py`
- `docs/realtime/guide.md`
+42
View File
@@ -0,0 +1,42 @@
# Realtime Tracing Architecture
Use this reference when reviewing or implementing Realtime tracing behavior, especially claims that `RealtimeSession` should emit the same trace hierarchy as `Runner`.
## Two Separate Tracing Systems
Realtime integrations involve two independent tracing paths:
| Path | Owner | Configuration | Result |
|---|---|---|---|
| Realtime API server tracing | Realtime API | `"auto"`, `workflow_name`, `group_id`, and `metadata` | The server creates a Realtime session trace in the Traces Dashboard. |
| Agents SDK client tracing | Agents SDK tracing provider | `trace()`, `agent_span()`, and other SDK span factories | The SDK exports locally created traces and spans through its tracing processor. |
The current Python SDK has no mapping from an Agents SDK client `trace_id`, `span_id`, or parent context into `RealtimeModelTracingConfig` or the model's `session.update`. A server-created Realtime trace is therefore not attached as a child of an SDK-created trace or span by this implementation. Likewise, adding an SDK `agent_span()` around `RealtimeSession` does not make server-side trace contents children of that span.
If both paths are enabled, the dashboard can contain two separate traces. A shared `group_id` can make them easier to filter and correlate, but it does not merge them or create a parent-child relationship.
## Current Python SDK Behavior
- `RealtimeModelTracingConfig` exposes only `workflow_name`, `group_id`, and `metadata` in `src/agents/realtime/config.py`.
- `OpenAIRealtimeWebSocketModel` defaults the Realtime tracing configuration to `"auto"` when the caller does not provide one.
- After receiving `session.created`, the model sends the tracing configuration through a `session.update` event.
- `RealtimeRunConfig.tracing_disabled` prevents the SDK from enabling Realtime tracing for that session.
Verify these paths in `src/agents/realtime/openai_realtime.py` and `src/agents/realtime/session.py`; do not rely on old issue descriptions because Realtime tracing support has changed over time.
## Maintainer Constraints
1. Identify whether the behavior belongs to the Realtime API's server trace or an Agents SDK client trace created with `trace()`.
2. A client-side agent span does not repair missing server tracing and does not create the unified hierarchy produced by `Runner`.
3. The current Python SDK cannot place server-created Realtime spans under an SDK-created trace or span because it does not carry client trace parentage through the Realtime tracing configuration. Recheck the live protocol with `$openai-knowledge` before treating that implementation gap as permanent.
4. Use the server trace for Realtime model activity. Use a shared `group_id` or metadata when correlation with a client trace is required.
5. Parallel SDK spans need an explicit product and maintenance contract covering the dual-trace user experience, async task context, handoff parenting, failure cleanup, and the client-only operations represented by those spans.
6. A client trace becoming non-empty is not evidence that Realtime server activity has been captured or parented correctly.
## Sources
- `src/agents/realtime/config.py`
- `src/agents/realtime/openai_realtime.py`
- `src/agents/realtime/session.py`
Recheck the official API reference with `$openai-knowledge` before changing this guidance or implementing new protocol behavior.
+79
View File
@@ -0,0 +1,79 @@
# Run Item Lifecycle
Use this reference for changes to model output processing, `RunItem` types, tool call and output items, stream events, replay conversion, session history, or serialized run state.
## Item Flow
The runtime carries one semantic item through several representations:
1. A model adapter returns provider output in `ModelResponse.output`.
2. `process_model_response()` converts recognized output into public `RunItem` objects and internal executable tool-run records in `ProcessedResponse`.
3. Tool execution and handoffs add output items and choose a `SingleStepResult.next_step`.
4. The resulting items feed `RunResult`, semantic stream events, session persistence, tracing, and `RunState` serialization.
5. Replayable items convert back to model input through `RunItem.to_input_item()` or `run_item_to_input_item()` after SDK-only metadata is handled.
Keep provider payloads, public run items, and internal execution records distinct. A provider item may be observable without requiring local execution, while a local tool-run record may need to preserve the selected SDK tool object and routing identity.
## Generated, Session, and Model Input Views
- `new_step_items` describes items generated by the current step.
- `session_step_items` preserves the full unfiltered sequence when session history must retain items that a handoff or input filter omitted from the next model request.
- `generated_items` is the public observability view and prefers `session_step_items` when present.
- Model input is a replay view, not the canonical storage view. Approval placeholders, SDK-only metadata, unsupported IDs, and orphaned calls may need filtering or normalization before an API request.
Do not force these views into one list. History persistence, user-visible results, and the next provider request have different correctness requirements.
## Adding or Changing an Item Type
Update every applicable surface together:
- `src/agents/items.py` for the public `RunItem` type, accessors, and replay conversion.
- `src/agents/run_internal/run_steps.py` for processed response and executable tool-run records.
- `src/agents/run_internal/turn_resolution.py` for provider output recognition, item creation, side effects, and next-step selection.
- `src/agents/run_internal/tool_execution.py`, `tool_actions.py`, or `tool_planning.py` for execution, dedupe, approvals, and outputs.
- `src/agents/run_internal/items.py` for normalization, replay conversion, fingerprints, dedupe, and provider-boundary metadata stripping.
- `src/agents/stream_events.py` and streaming queue helpers for public semantic events.
- `src/agents/run_state.py` for serialization and deserialization when the item can survive interruption.
- `src/agents/run_internal/session_persistence.py` for session conversion, sanitization, and retry accounting.
- Tracing and usage conversion when the item contributes observable tool or model work.
## Compatibility Rules
- Public stream event names are compatibility-sensitive. Do not rename an existing event, even to fix spelling, without an explicit breaking-change plan.
- Preserve provider-supplied IDs and opaque provider data until the owning boundary deliberately removes them. Do not invent IDs or coerce malformed values to make replay appear valid.
- Preserve SDK-only metadata needed for display, routing, approvals, tool origin, or resume, but strip it before sending payloads to a provider that does not accept it.
- Tool call and output pairs must retain the same string call ID across execution, replay, session persistence, and resume.
- Empty, falsey, structured, image, file, and custom tool outputs are valid values unless the public tool contract explicitly rejects them; do not use broad truthiness checks to decide whether output exists.
## Replay Integrity
- Prune orphan calls only from runner-generated or resumed history where the SDK owns call/output pairing. Preserve caller-supplied initial input unless an explicit public normalization contract says otherwise.
- When dropping an orphan tool call, also drop reasoning items tied to that removed call so the provider does not receive a reasoning item without its required following item. Do not drop a lone reasoning item merely because its following item is absent locally; server-managed conversation state may own that item.
- `reasoning_item_id_policy="omit"` strips IDs only from SDK-generated follow-up reasoning items. It does not rewrite initial caller input, must survive `RunState` resume, and can be superseded by a later `call_model_input_filter` that deliberately returns IDs.
- Pair anonymous tool-search outputs with the latest compatible anonymous call and never pair a named call with an anonymous output. A missing call ID does not justify inventing a persistent provider identity.
- `provider_data` and provider IDs have boundary-specific ownership. Preserve them for raw results and provider requests that accept them, but strip private or replay-unsafe metadata from session and server-conversation history where the SDK contract requires sanitized items.
## Review Checklist
1. Follow the item from provider response through result, stream, session, replay, and `RunState`.
2. Test both typed provider objects and mapping payloads when adapters support both.
3. Verify IDs, metadata, and output values survive every required round-trip.
4. Test filtering and dedupe without losing the latest valid call/output pair.
5. Compare streaming event order with the non-streaming item sequence.
6. Test orphan pruning and reasoning pairing with client-managed replay and server-managed continuation separately.
## Sources
- `src/agents/items.py`
- `src/agents/stream_events.py`
- `src/agents/run_internal/items.py`
- `src/agents/run_internal/run_steps.py`
- `src/agents/run_internal/turn_resolution.py`
- `src/agents/run_internal/session_persistence.py`
- `src/agents/run_state.py`
- `tests/test_items_helpers.py`
- `tests/test_run_internal_items.py`
- `tests/test_stream_events.py`
- `tests/test_run_state.py`
- `docs/running_agents.md`
- `docs/results.md`
+67
View File
@@ -0,0 +1,67 @@
# Runner Lifecycle
Use this reference for changes to `Runner`, turn accounting, guardrails, hooks, handoffs, interruptions, cancellation, or streaming and non-streaming behavior.
## Turn Boundary
A turn is one logical model invocation plus processing of that response. Tool execution, handoff resolution, session persistence, interruption resume, and retries inside that logical invocation do not independently consume turns.
- Increment the turn counter exactly once when the run loop starts a logical model turn. Transport or provider retries inside `get_new_response()` remain part of that turn.
- A handoff changes the current agent, but the next turn begins only when the new agent invokes a model.
- Resuming `NextStepInterruption` continues the paused turn. Resolve stored approvals and tool work before deciding whether another model call is needed.
- Preserve `max_turns` and the current turn in `RunState`; resume must not reset the budget or charge a turn twice.
## Guardrail Ordering
- Input guardrails belong to the starting agent and run only for the initial user input. Do not rerun them after handoffs or when resuming an interruption.
- Sequential input guardrails must finish before model-side effects begin. Parallel input guardrails may overlap the model call, so a tripwire or exception must cancel and await the in-flight model task and sibling guardrail tasks.
- Tool input guardrails run before the approved tool side effect. Tool output guardrails run after local execution and before the output is accepted into the next step.
- Output guardrails run only after a candidate final output exists. Streaming must await them and preserve the same tripwire and exception behavior as non-streaming execution before declaring completion.
- Guardrail results are observable run state. Preserve them across handoffs, error handlers, streamed completion, and `RunState` round-trips.
## Step State Machine
`SingleStepResult.next_step` is the control boundary after one model response and its local side effects:
| Step | Meaning |
|---|---|
| `NextStepRunAgain` | Continue with the current agent and make another model call |
| `NextStepHandoff` | Switch the current agent, emit the transition, then continue |
| `NextStepFinalOutput` | A final candidate exists; finish terminal hooks, output guardrails, persistence, and result construction |
| `NextStepInterruption` | Persist enough processed state to resume pending approvals without rerunning completed work |
Do not bypass this state machine with path-local completion logic. New terminal or pausable behavior must define non-streaming, streaming, session, tracing, and serialized-resume semantics.
## Streaming Parity and Cancellation
- Streaming and non-streaming paths must produce equivalent final output, generated items, current agent, usage, guardrail results, session history, and interruption state for the same model behavior.
- Raw transport events may differ, but semantic `RunItemStreamEvent` and `AgentUpdatedStreamEvent` emission must follow the same processed items and agent transitions used by the non-streaming result.
- `stream_events()` is the stream driver's cleanup boundary. Keep consuming it until exhaustion after normal completion or `cancel()`, or explicitly close the async iterator; merely breaking after the last visible token does not prove session writes, guardrails, compaction, sandbox cleanup, usage, or terminal errors have settled.
- Immediate cancellation marks the result complete and requests task cancellation. `after_turn` cancellation leaves the current model/tool turn running so it can persist state and usage before the next turn. Preserve this distinction instead of treating both modes as queue shutdown.
- Terminal run-loop, guardrail, and max-turn errors must be surfaced from `stream_events()` after the required queued events are handled. Preserve `run_loop_exception` as a diagnostic view of the background task, not as a replacement completion primitive.
- `task.cancel()` is a request, not cleanup completion. Await cancelled tasks when their `finally` blocks, exceptions, or owned resources affect run correctness.
- Keep lifecycle hooks aligned across both paths, especially model start/end, handoff, tool start/end, and final-output hooks.
## Review Checklist
1. Identify which turn and which agent own the behavior.
2. Trace every `NextStep` outcome, including interruption resume.
3. Compare streaming and non-streaming side effects and terminal ordering.
4. Test guardrail tripwires and exceptions in sequential and parallel modes when relevant.
5. Verify normal exhaustion, explicit iterator close, immediate cancellation, and after-turn cancellation leave the documented result and owned resources in a coherent state.
## Sources
- `src/agents/run.py`
- `src/agents/run_internal/run_loop.py`
- `src/agents/run_internal/run_steps.py`
- `src/agents/run_internal/turn_preparation.py`
- `src/agents/run_internal/turn_resolution.py`
- `src/agents/run_internal/guardrails.py`
- `tests/test_agent_runner.py`
- `tests/test_agent_runner_streamed.py`
- `tests/test_cancel_streaming.py`
- `tests/test_guardrails.py`
- `tests/test_run_state.py`
- `docs/streaming.md`
- `docs/results.md`
+64
View File
@@ -0,0 +1,64 @@
# RunState Schema and Resume Boundary
Use this reference for changes involving `RunState` serialization, deserialization, approvals, trace state, sandbox state, agent identity, tool output payloads, or any persisted resume data.
## Compatibility Boundary
`RunState` is the durable SDK pause/resume boundary. Treat the serialized JSON shape as compatibility-sensitive once a schema version has shipped in a release.
- `to_json()` always emits `CURRENT_SCHEMA_VERSION`.
- `from_json()` must continue reading every version in `SUPPORTED_SCHEMA_VERSIONS`.
- Older SDKs intentionally reject newer or unsupported versions rather than attempting forward compatibility.
- Unreleased schema versions may be renumbered or squashed before release when intermediate snapshots are intentionally unsupported.
- Every supported version must have a non-empty one-line entry in `SCHEMA_VERSION_SUMMARIES`.
## When to Bump the Schema
Bump `CURRENT_SCHEMA_VERSION` when a serialized `RunState` snapshot changes in a way that affects resume correctness or would silently lose data when read under an older schema label.
Examples include:
- New persisted fields on `RunState`, `ModelResponse`, `ProcessedResponse`, interruptions, approvals, tool outputs, sandbox state, trace state, or agent-owned state.
- New run item, tool call, approval, or output item variants that can appear in serialized state.
- New SDK-only metadata needed to route, dedupe, approve, retry, or resume a tool call.
- A changed meaning for an existing serialized field.
Do not rely on current-reader tests alone. Add a regression that rewrites `$schemaVersion` to an older supported label when appropriate and proves the old label is accepted, rejected, or migrated deliberately.
## Identity and Routing State
Serialized state must preserve enough identity to resume without changing behavior:
- Agent identity must distinguish duplicate agent names in the same graph.
- Function tools should persist canonical lookup keys, including `bare`, `namespaced`, and `deferred_top_level`.
- Tool call IDs must remain provider-supplied strings; do not coerce arbitrary values into IDs.
- Approval decisions and rejection messages must restore against the same tool identity and call ID they originally targeted.
- The per-agent tool-use tracker must preserve stable duplicate-agent identity so tool-choice reset behaves the same after resume.
- Server-managed conversation identifiers must restore into `OpenAIServerConversationTracker` without replaying acknowledged input.
## Context and Secrets
Context serialization is intentionally conservative.
- Mapping contexts can round-trip directly.
- Custom contexts need explicit serializers and deserializers when exact restoration matters.
- Without a safe serializer, snapshots may record metadata and warnings rather than the raw object.
- Do not persist secrets in `RunContextWrapper.context`, trace data, tool outputs, or custom data unless the caller explicitly chose that durability boundary.
## Review Checklist
1. Identify every serialized field whose shape or meaning changes.
2. Decide whether the affected schema version is released or unreleased.
3. Update `CURRENT_SCHEMA_VERSION` and `SCHEMA_VERSION_SUMMARIES` when resume compatibility requires it.
4. Keep released schema versions readable, or fail with an explicit compatibility error if the old label cannot safely represent the new data.
5. Test `to_json()` output, `from_json()` restoration, string round-trips, and resumed execution through the public `Runner.run(...)` or `Runner.run_streamed(...)` path.
## Sources
- `src/agents/run_state.py`
- `src/agents/result.py`
- `src/agents/run_internal/agent_runner_helpers.py`
- `src/agents/run_internal/oai_conversation.py`
- `src/agents/run_internal/run_steps.py`
- `src/agents/run_internal/tool_execution.py`
- `tests/test_run_state.py`
@@ -0,0 +1,70 @@
# Sandbox Runtime Boundary
Use this reference for changes to sandbox session ownership, `SandboxAgent` preparation, manifests, capabilities, host-path materialization, snapshots, resume state, agent transitions, or cleanup.
## Runtime Ownership
The outer `Runner` owns agent turns, approvals, handoffs, tracing, session history, and `RunState`. A sandbox session owns the execution environment, workspace, processes, mounts, and provider-specific connection state. Do not move one layer's lifecycle into the other without defining resume and cleanup behavior for both.
- A live `SandboxRunConfig.session` is caller-owned. The runner may configure and use it but must not delete or fully tear it down.
- A session created or resumed through `SandboxRunConfig.client` is runner-owned. Cleanup runs pre-stop hooks, persists snapshot-backed workspace state, stops and shuts down the session, deletes provider resources when required, and closes dependencies.
- Session cleanup must be idempotent and release acquired `SandboxAgent` concurrency guards even when persistence or provider cleanup fails.
- A `SandboxAgent` instance cannot be reused concurrently across runs because prepared capability tools and session state are bound to one live run. Clone or construct separate agents for concurrent work.
## Session Source and Saved State
Resolve the session source in this order: injected live session, resumable sandbox state carried by `RunState`, explicit `SandboxRunConfig.session_state`, then a newly created session. Manifest and snapshot inputs seed only a fresh session; they do not overwrite an injected or resumed workspace.
- `RunState` sandbox data and explicit `session_state` represent provider connection or session state used to reconnect to existing work.
- A snapshot represents saved workspace contents used to seed a new session. It is not interchangeable with provider session state.
- Preserve stable per-agent resume identity across handoffs, including graphs with duplicate agent names. Object identity is process-local, so serialized state needs stable keys and explicit current-agent selection.
- Serialize runner-owned sessions after stop-time persistence has completed so a later resume can reattach when the backend survives or reconstruct the workspace from the saved snapshot when it does not.
## Agent Preparation
- Clone capability instances per run before binding them to a live session. Reusing mutable capability objects can leak tools, sampling settings, or session references across runs.
- Validate capability dependencies before exposing tools. Capability tool construction, instruction fragments, input processing, and sampling adjustments must use the same effective capability set.
- Build instructions in the documented order: SDK sandbox base prompt or explicit replacement, agent instructions, capability instructions, remote-mount policy, then the rendered filesystem description.
- Bind capability tools to the live session and preserve a link from the prepared clone to the public `SandboxAgent`. Dynamic instructions and hooks should observe the public agent rather than an internal clone with implementation-only state.
- Handoffs stay in the outer run loop and select another agent-bound sandbox session. A nested `Agent.as_tool()` run owns its own nested runner and sandbox lifecycle.
## Filesystem Trust Boundary
- Manifest entry destinations are workspace-relative and must not escape the workspace. The workspace root itself must be absolute where the backend requires an absolute runtime root.
- `LocalFile` and `LocalDir` sources are host-side inputs. Resolve them against a trusted base directory, require explicit application-controlled `extra_path_grants` outside that base, and reject untrusted manifests that try to authorize their own host access.
- Validate local sources at use time, not only when parsing the manifest. Defend against symlinked sources, parent-directory swaps, platform path aliases, and archive members that change meaning between validation and extraction.
- Archive extraction must reject traversal, unsafe links, and unsupported member types before writing, and enforce entry, byte, and expansion limits without materializing an unbounded member list.
- Extra path grants are runtime access, not durable workspace content. Snapshots and `persist_workspace()` include the workspace root, not arbitrary granted paths.
- Credentials for mounts or providers must remain in the owning adapter and must not appear in generated shell commands, model-visible errors, logs, or serialized sandbox state.
## Provider and Error Boundary
- Normalize backend failures to sandbox errors without discarding provider details needed for diagnosis. Preserve explicit retryability instead of inferring it later from a message string.
- Keep portable sandbox paths separate from host filesystem paths and provider identifiers. Conversion belongs in the backend or materialization boundary, not in agent-facing tools.
- Temporary clones, mounts, sinks, and dependency resources need failure cleanup during partial startup as well as normal shutdown.
- Capability tools should report bounded output and preserve provider exit status or structured error data without exposing private runtime metadata to the model.
## Review Checklist
1. Name the owner of every live session, provider client, mount, process, capability, and temporary resource.
2. Test injected, resumed, explicit-state, snapshot-seeded, and fresh-session paths separately.
3. Verify handoffs, duplicate agent names, interruption resume, and cleanup failure preserve the intended session mapping.
4. Test host-path, symlink, traversal, archive-limit, and credential-redaction boundaries on applicable platforms.
5. Exercise the public `Runner` path so agent preparation, capability binding, persistence, and cleanup run together.
## Sources
- `docs/sandbox/guide.md`
- `docs/sandbox/clients.md`
- `src/agents/sandbox/runtime.py`
- `src/agents/sandbox/runtime_session_manager.py`
- `src/agents/sandbox/runtime_agent_preparation.py`
- `src/agents/sandbox/manifest.py`
- `src/agents/sandbox/materialization.py`
- `src/agents/sandbox/workspace_paths.py`
- `src/agents/sandbox/session/archive_extraction.py`
- `tests/sandbox/test_runtime.py`
- `tests/sandbox/test_runtime_agent_preparation.py`
- `tests/sandbox/test_session_state_roundtrip.py`
- `tests/sandbox/test_materialization.py`
- `tests/sandbox/test_extract.py`
+80
View File
@@ -0,0 +1,80 @@
# Session Persistence
Use this reference for changes to client-managed sessions, session input callbacks, per-turn persistence, retries, rewind, compaction replacement, or session backend implementations.
Read [Conversation state ownership](conversation-state-ownership.md) first when server-managed continuation is also involved. A client-managed session is a history store; it is not a second owner for a server-managed conversation.
## Session Contract
- `get_items(limit=N)` returns the latest `N` items in chronological order.
- `add_items()` appends one logical batch. Backends should make the batch atomic so partial turns are not visible after failure.
- `pop_item()` removes the current tail item and is used only for guarded rollback of items the current run can prove it owns.
- `clear_session()` clears the session boundary; compaction decorators that replace history must provide stronger restore behavior around destructive replacement.
Third-party implementations target the `Session` protocol. Internal base classes and backend-specific metadata are not the compatibility contract unless explicitly documented.
## Backend Consistency
- An explicit `get_items(limit=N)` argument overrides the backend's default session limit. Return the latest `N` items in chronological order, with a deterministic tie-breaker when timestamps can collide.
- Preserve caller batch order. Persist the items and any indexes or structural metadata required to read them as one atomic operation. A failed batch must leave earlier history unchanged, and any backend-internal retry must not create duplicates.
- Serialize initialization and conflicting writes at the backend's actual consistency boundary. Concurrent first writers must not race, and cancellation or failure must not strand locks or transactions.
- Apply configured table or collection names and session settings consistently across reads, writes, deletes, metadata updates, and wrapper operations.
- For backends that deserialize stored records, a corrupt record must not hide valid history or cause unrelated records to be deleted. Define consistent `get_items()` and `pop_item()` behavior that isolates the bad record and continues safely.
- Preserve creation timestamps and advance update timestamps deliberately. Backend-only identifiers and metadata must not leak into model-facing session items.
- Close only resources the backend owns. An injected engine, client, or connection remains caller-owned unless the public contract explicitly transfers ownership.
## Preparing Input Versus Persisting Input
`prepare_input_with_session()` returns two different values: the normalized input for the next model request and the subset of new-turn items that should be appended to the session.
- Existing history must not be re-appended as new input, even when `session_input_callback` deep-copies, reorders, filters, duplicates, or reconstructs items.
- A callback may change the model view without rewriting already stored history.
- Handoff and model-input filters may omit items from the next request while `session_step_items` retains the complete unfiltered sequence for history and observability.
- Normalize and deduplicate the model request and persistence candidates through the same canonical item helpers, then apply boundary-specific sanitization.
## Per-Turn Save and Resume
- Persist each completed turn, not only the final run result. Tool outputs and handoff items must survive a later error or interruption.
- `_current_turn_persisted_item_count` tracks which generated items have already been saved during streaming, retry, or resume. Count items after conversion and persistence filtering, not from the unsanitized source list.
- Resuming an interruption must save newly produced approval and tool output items without duplicating inputs or previously persisted outputs.
- Preserve full session items separately from filtered model input when updating `RunState` after resume.
- A guardrail trip must preserve the accepted user input while excluding speculative assistant or tool work that the tripwire invalidated. Test sequential and parallel guardrails in streaming and non-streaming modes because their persistence timing differs even though the resulting history must remain coherent.
## Retry Rewind
Retry cleanup is ownership-sensitive and best effort.
- Rewind only an exact serialized suffix that belongs to the failed attempt. Never scan backward and delete merely similar historical items.
- Verify the complete suffix before popping. If a pop fails or returns an unexpected item, restore already popped items in chronological order.
- Wait for backends with asynchronous cleanup semantics before starting the next retry when stale tail items could be observed.
- Do not forward live `RunContextWrapper` objects through retry rewind or compaction storage paths unless the session API explicitly owns that runtime context.
## Compaction Replacement
- Treat history replacement as a transaction: capture the prior state, apply the compacted state, and restore the prior state if clear or replacement fails.
- Defer response-based compaction while local tool outputs still need to be associated with the response chain.
- Choose input-based or previous-response-based compaction according to the actual state owner and `store` behavior; do not combine a local replay with a server-owned history chain.
- Compaction output is a run item and must follow the item lifecycle, session sanitization, and `RunState` rules rather than bypassing them as backend-only data.
## Review Checklist
1. Distinguish model input, new-turn persistence candidates, and full session history.
2. Test atomic failure, duplicate content, reordered callbacks, and filtered handoff input.
3. Test save behavior after tool execution, handoff, guardrail trip, interruption, and resume.
4. Prove retry rewind removes only the attempt-owned suffix and restores on partial failure.
5. Test compaction replacement failures without losing the previous history.
6. Test backend ordering, atomic batches, concurrent first writes, configured names and limits, corrupt records, and resource ownership.
## Sources
- `src/agents/memory/session.py`
- `src/agents/memory/session_settings.py`
- `src/agents/memory/sqlite_session.py`
- `src/agents/extensions/memory/`
- `src/agents/run_internal/session_persistence.py`
- `src/agents/run_internal/items.py`
- `src/agents/run_internal/run_steps.py`
- `tests/memory/`
- `tests/extensions/memory/`
- `tests/test_agent_runner.py`
- `tests/test_agent_runner_streamed.py`
@@ -0,0 +1,64 @@
# Tool Execution Lifecycle
Use this reference for changes to function-tool planning, approvals, tool guardrails, concurrency, cancellation, timeouts, hooks, error conversion, or resumed execution. Read [Tool identity and routing](tool-identity.md) when names, namespaces, lookup keys, or call IDs also change.
## Plan Before Side Effects
`process_model_response()` discovers executable work, but `tool_planning.py` decides which work may run now. Keep discovery, approval partitioning, and invocation as separate phases.
- Fresh and resumed turns need different plans. A resumed interruption must execute unresolved or newly approved work without rediscovering or rerunning completed calls.
- Approval state is authoritative once resolved. Do not call a dynamic `needs_approval` checker again for a call whose status is already approved or rejected.
- Deduplicate by invocation identity before execution while preserving model order for public call and output items. A repeated tool definition is not a repeated call, and a repeated call ID must not execute twice.
- Validate enabled tools and canonical lookup before side effects. A tool disabled after model output or absent from the resolved tool set must follow the configured missing-tool behavior rather than reaching a stale callable.
## Approval and Guardrail Ordering
- Pre-approval input guardrails are an early rejection optimization. They may run before an approval interruption, but input guardrails must run again immediately before invocation because state, policy, or arguments may have changed while approval was pending.
- Rechecking guardrails does not mean rechecking approval. Persisted approval decisions and rejection messages must remain attached to the same tool identity and call ID across `RunState` resume.
- Tool input guardrails finish before the local side effect. Tool output guardrails finish before output becomes accepted run state, model input, or persisted session history.
- The tool guardrail pipeline applies to `FunctionTool` invocation. Handoffs, hosted tools, built-in provider tools, and nested `Agent.as_tool()` runs have separate execution boundaries unless they explicitly opt into equivalent checks.
## Concurrency and Failure Semantics
SDK-side function-tool concurrency is independent of provider-side parallel tool-call generation. The provider controls how many calls appear in one response; `RunConfig.tool_execution.max_function_tool_concurrency` controls how many local function handlers run at once.
- Preserve model order in emitted outputs even when handlers complete out of order.
- Isolate sibling results. A cancelled or failed call must not discard outputs already produced by successful siblings.
- Distinguish cancellation of one tool handler from cancellation of the parent run. Tool-local cancellation can follow the configured tool failure policy; parent cancellation must propagate promptly instead of becoming model-visible tool output.
- `task.cancel()` is not terminal cleanup. On sibling failure, drain cancelled handlers and wait for post-invocation work within the bounded cleanup policy. On parent cancellation, cancel remaining tasks and attach result callbacks so late exceptions are observed without delaying cancellation indefinitely.
- Select and raise failures deterministically when several tasks fail, while still observing secondary failures. Do not let task-set iteration order or eager task execution change the public result.
## Invocation Boundary
- Decorated synchronous Python functions run through `asyncio.to_thread()` so they do not block the event loop. Async function tools run in the event loop and are the only decorated handlers that support SDK timeouts.
- Timeout handling and ordinary exception handling are distinct policies. `timeout_behavior` and `timeout_error_function` own timeout conversion; `failure_error_function=None` means ordinary exceptions propagate instead of becoming model-visible output.
- Tool start/end hooks and function spans surround the actual invocation once per call, including failure and cancellation paths. Do not emit a successful end state before output guardrails complete.
- Per-run resources such as resolved `Computer` implementations must be initialized and disposed by the run that acquired them.
- Nested `Agent.as_tool()` execution owns a nested run loop and nested resumable state. Scope cached nested state by the parent `RunState` and call identity, not only by the reusable agent or tool object.
- `AgentToolUseTracker` records tool use per agent identity. When `reset_tool_choice=True`, reset the effective next-turn tool choice after that agent uses a tool so `required` or a named choice cannot force an accidental loop; do not mutate the agent's declared settings across independent runs.
- Persist and restore the tool-use tracker across interruption and sandbox resume, including graphs with duplicate agent names, so resumed tool-choice behavior matches uninterrupted execution.
## Review Checklist
1. Trace fresh execution, approval interruption, approval rejection, and serialized resume separately.
2. Verify guardrail, approval, hook, trace, invocation, output, and persistence order.
3. Test sequential, bounded-concurrency, sibling failure, tool-local cancellation, and parent cancellation paths.
4. Test default, custom, and disabled failure conversion plus timeout behavior where applicable.
5. Confirm every started task and per-run resource reaches a deterministic terminal state.
## Sources
- `docs/running_agents.md`
- `docs/tools.md`
- `docs/guardrails.md`
- `docs/human_in_the_loop.md`
- `src/agents/run_internal/tool_planning.py`
- `src/agents/run_internal/tool_execution.py`
- `src/agents/tool.py`
- `tests/test_agent_runner.py`
- `tests/test_agent_runner_streamed.py`
- `tests/test_function_tool.py`
- `tests/test_tool_guardrails.py`
- `tests/test_tool_choice_reset.py`
- `tests/test_tool_use_tracker.py`
- `tests/test_run_state.py`
+71
View File
@@ -0,0 +1,71 @@
# Tool Identity and Routing
Use this reference for changes involving function-tool names, namespaces, provider wire names, lookup, approvals, tracing, MCP exposure, handoffs, or tool call IDs.
## Identity Layers
One tool can have several related identifiers. They are not interchangeable.
| Layer | Purpose | Canonical source |
|---|---|---|
| Public name | User- and model-facing tool name | `tool.name` |
| Explicit namespace | Distinguishes tools with the same public name | Tool namespace metadata |
| Qualified or dispatch name | Routes a model call to the intended tool | `namespace.name` when a namespace exists |
| Lookup key | Collision-free internal identity | `bare`, `namespaced`, or `deferred_top_level` tuple |
| Approval keys | Matches approval decisions to the intended tool | Canonical qualified and permitted alias keys |
| Trace name | Human-readable tracing label | Explicit trace name or public name |
| Call ID | Identifies one invocation, not the tool definition | Provider-supplied string |
Do not collapse these layers into one string or introduce local rules that only one caller uses.
## Canonical Helpers
Use `src/agents/_tool_identity.py` as the single implementation layer. Important helpers include:
- `get_function_tool_lookup_key_for_tool()` and `get_function_tool_lookup_key_for_call()` for canonical lookup identity.
- `get_function_tool_dispatch_name()` and `get_function_tool_qualified_name()` for routing and display surfaces that require qualification.
- `get_function_tool_approval_keys()` for approval matching.
- `get_function_tool_trace_name()` and `get_tool_call_trace_name()` for trace labels.
- `validate_function_tool_lookup_configuration()` and `build_function_tool_lookup_map()` for collision detection and dispatch maps.
- `normalize_tool_call_for_function_tool()` when provider payloads must be normalized for a selected tool.
If a proposed change bypasses these helpers, first prove that the target surface has intentionally different semantics.
## MCP and Handoff Rules
- `include_server_in_tool_names` is opt-in. Server-prefixed MCP names affect the model-exposed collision-safe name; they do not rename the original tool on the MCP server.
- Reserved names and enabled handoff names participate in collision avoidance only on the paths that expose generated model-facing names.
- `Handoff.default_tool_name()` is the source of default handoff tool names. Keep Realtime and non-Realtime handoff conversion aligned with it.
- Do not forward a naming option through a path where the downstream helper does not consult it and then describe the change as runtime behavior. Trace the complete caller-to-dispatch path first.
## Deferred Tool Search Rules
- A top-level `FunctionTool` with `defer_loading=True` and no explicit namespace uses the synthetic lookup key `("deferred_top_level", tool.name)`.
- The Responses wire shape for a loaded deferred top-level tool can look like `namespace == name`. Treat that namespace as reserved for the synthetic deferred tool-search path, not as a normal explicit namespace.
- `tool_namespace()` must reject an explicit namespace that equals the inner tool name. Otherwise a normal namespaced tool and a deferred top-level tool would have the same wire shape.
- Preserve the synthetic namespace on approval, interruption, tracing, and `ToolContext` surfaces when it identifies the model call, but dispatch the actual local tool through the deferred lookup key and strip the synthetic namespace before invoking the tool.
- Permanent approvals for deferred top-level tools should key by `deferred_top_level:<name>`. A bare-name approval alias is allowed only when no visible bare sibling can make that alias ambiguous.
## Tool Call ID Rules
- Preserve provider-supplied string call IDs across call items, approvals, outputs, retries, and serialized state.
- Do not coerce arbitrary values with `str(...)`. Canonical extractors return a call ID only when the source value is already a string.
- Do not use a call ID as a tool-definition identity or a tool name as an invocation identity.
- When a provider omits a stable identifier, use an existing fingerprint or dedupe policy for that item type instead of inventing a cross-provider ID contract.
## Review Checklist
1. Identify every identifier layer affected by the change.
2. Trace the actual runtime path from model-visible name to lookup, approval, invocation, output, and trace metadata.
3. Compare adjacent canonical helpers before adding conversion or fallback behavior.
4. Test collisions between bare, namespaced, deferred, MCP, local function, and handoff tools when applicable.
5. Require a regression test that fails on the base and proves the model-visible or dispatch behavior, not only an intermediate argument value.
## Sources
- `src/agents/_tool_identity.py`
- `src/agents/agent.py`
- `src/agents/mcp/`
- `src/agents/handoffs/__init__.py`
- `src/agents/run_internal/tool_execution.py`
- `src/agents/run_state.py`
+58
View File
@@ -0,0 +1,58 @@
# Tracing Lifecycle
Use this reference for changes to SDK trace or span context, processors, export, flush, shutdown, resumed trace state, or sensitive-data handling. Read [Realtime tracing architecture](realtime-tracing.md) before applying these client-side rules to Realtime server traces.
## Context and Parenting
- The current trace and span are held in `ContextVar` state. Async tasks inherit a snapshot when created; later changes in a child task do not rewrite the parent task's context.
- A context token must be reset in the context that created it. Start and finish ownership cannot be transferred between tasks without an explicit context boundary.
- A no-op trace or span cannot be a real parent. Propagate no-op behavior instead of exporting children with the sentinel `no-op` trace or span ID.
- Span factories should inherit trace metadata needed by processors, but they must not mutate the trace's caller-owned metadata mapping.
## Run and Resume Ownership
- A runner-created trace encloses run-loop-owned guardrails, model calls, tool execution, handoffs, session persistence, and error handling. Do not assume every completion callback or resource cleanup runs before trace finish; place newly traced cleanup explicitly inside the trace lifetime or create a deliberate separate trace/span context.
- An existing caller trace remains caller-owned. `Runner` may create child spans but must not finish or flush the caller's trace.
- `RunState` stores enough trace metadata to continue an interrupted run. Resume may reattach only when the trace ID was previously started in the process and the effective workflow name, group ID, metadata, and tracing key identity still match.
- Reattachment must not emit a duplicate trace-start event. If the saved state cannot prove a compatible live trace, create a normal trace according to the current run configuration instead of pretending to resume the old context.
- Tracing API keys are omitted from serialized `RunState` by default. A hash can verify that the caller supplied the same explicit key without persisting the secret; raw key persistence is opt-in.
## Processor and Export Isolation
- Trace processors are observability extensions and must not change application success. Catch processor callback, exporter, flush, and shutdown failures and report them as non-fatal.
- The default batch worker starts lazily on first queued item to avoid import-time thread and fork hazards. Keep top-level imports free of worker creation and shutdown-handler duplication.
- An exporter exception must not kill the batch worker and strand future traces. Drop or report the failed batch according to policy, then keep the worker usable.
- `flush_traces()` waits for queued and in-flight export work, so callers should invoke it after the trace closes when they require immediate delivery. It is not a substitute for finishing a partially built trace.
- Shutdown is best effort and deadline-aware. It should request exporter shutdown, interrupt retry backoff, drain within the remaining deadline, and return without changing the process exit code when an exporter blocks or a backend remains unavailable.
- Keep `TraceProvider.force_flush()` and `shutdown()` defaulting to no-ops for compatibility with custom providers that predate these lifecycle methods.
## Data Boundaries
- `trace_include_sensitive_data=False` controls captured span payload fields; it does not automatically sanitize exception objects, chaining, tracebacks, logs, or telemetry created elsewhere.
- Redaction must cover `__cause__`, `__context__`, formatter failures, and model-visible error conversion when an original exception carries tool arguments or provider payloads. `raise ... from None` changes display, not object retention.
- The OpenAI trace exporter owns ingest-specific payload sanitization such as field-size limits and supported usage keys. Custom processors should continue receiving the SDK's normal trace data unless their contract says otherwise.
- Per-run tracing keys, organization, and project routing must stay attached to the trace or exported item that selected them; do not let mutable global exporter state reroute an already-created trace.
## Review Checklist
1. Identify which task and context own each trace and span start, finish, and token reset.
2. Test success, exception, cancellation, interruption, serialized resume, full stream exhaustion, and explicit stream close.
3. Verify processor and exporter failures remain non-fatal and do not kill later export work.
4. Test flush and shutdown with queued work, in-flight export, retry backoff, and a blocking exporter.
5. Audit sensitive data through span payloads, exception chains, logs, and serialized state.
## Sources
- `docs/tracing.md`
- `src/agents/tracing/context.py`
- `src/agents/tracing/scope.py`
- `src/agents/tracing/traces.py`
- `src/agents/tracing/spans.py`
- `src/agents/tracing/provider.py`
- `src/agents/tracing/processors.py`
- `src/agents/tracing/setup.py`
- `src/agents/run_state.py`
- `tests/test_trace_processor.py`
- `tests/test_tracing.py`
- `tests/test_run_state.py`
- `tests/tracing/test_import_side_effects.py`
@@ -0,0 +1,56 @@
# Voice Pipeline Lifecycle
Use this reference for changes to `VoicePipeline`, `AudioInput`, `StreamedAudioInput`, STT sessions, TTS task ordering, voice lifecycle events, PCM framing, result streaming, or voice tracing. Realtime agents use a different live-session architecture; read [Realtime session lifecycle](realtime-session-lifecycle.md) for that path.
## Pipeline Ownership
`VoicePipeline` owns an STT-to-workflow-to-TTS producer task and returns a `StreamedAudioResult` that drives its observable completion.
- Static `AudioInput` produces one transcription and one workflow turn. `StreamedAudioInput` creates a long-lived transcription session and runs one workflow turn for each emitted transcript until the input or session ends.
- The multi-turn pipeline owns the transcription session and closes it in `finally` before marking output complete. Partial setup and workflow failure must not strand the STT connection or producer task.
- `workflow.on_start()` applies only to the streamed multi-turn path. Its failure is logged and skipped so the transcription session can still start; normal per-turn workflow failures are terminal and surface through the result stream.
- The SDK does not provide application-level interruption handling for `StreamedAudioInput`. Lifecycle events expose turn boundaries, but microphone muting, playback interruption, and barge-in policy remain application-owned.
## Text, Audio, and Event Ordering
- A workflow can yield multiple text fragments. The text splitter returns ready-to-synthesize text plus a remainder; synthesize non-empty ready text even when it is shorter than a default sentence threshold, and retain the remainder for the turn's final flush.
- TTS segment tasks may run concurrently, but `_ordered_tasks` and the dispatcher must emit their audio and lifecycle events in workflow text order rather than completion order.
- `turn_started` precedes audio for that turn. `turn_ended` is emitted only after the turn's final text remainder has been synthesized and its audio dispatched. `session_ended` follows all ordered segment queues and all turns.
- A `VoiceStreamEventError` terminates result streaming and the stored exception is raised after task cleanup. `session_ended` is a lifecycle marker, not proof of success; consumers must still observe the terminal exception from `stream()`.
- Consuming `StreamedAudioResult.stream()` is the public completion and error boundary. On normal `session_ended`, let the producer finish before cleanup so session close and trace end are not cancelled by result teardown.
## PCM and Caller Data
- PCM16 samples span two bytes. Preserve a trailing half-sample across TTS chunks, combine it with the next chunk, and pad only the final unmatched byte at end of segment.
- Apply `buffer_size` to TTS source chunks without changing sample order. Convert to float32 only after PCM16 framing is complete, then apply caller-provided `transform_data` to each emitted array.
- `AudioInput.to_base64()` and audio-file conversion must not mutate the caller's NumPy buffer when converting float input to PCM16.
- Empty input and empty text-splitter output are valid boundaries. They must not cause NumPy reduction errors, phantom TTS calls, or missing turn/session lifecycle events.
## Trace Lifetime and Data
- The pipeline trace stays active for the full asynchronous producer lifecycle, not only until `VoicePipeline.run()` returns its result object.
- Each output turn owns a speech-group span and each synthesized segment owns a child speech span. Finish the turn span after ordered audio dispatch and finish the pipeline trace after STT session close and output completion.
- Text and audio sensitivity are independent controls. `trace_include_sensitive_data` governs transcript and TTS text, while `trace_include_sensitive_audio_data` governs encoded audio payloads.
- Error paths must finish active speech spans and the enclosing trace without replacing the original pipeline exception.
## Review Checklist
1. Test static and streamed input, including STT setup failure, workflow failure, TTS failure, and transcription-session close.
2. Verify fragment concurrency never changes audio, turn, or session event order.
3. Test short splitter output, empty output, odd-byte chunks, cross-chunk sample boundaries, int16, and float32 conversion.
4. Consume the public result stream and verify terminal errors, task cleanup, session close, and trace-end order.
5. Confirm sensitive text and audio are independently omitted from trace payloads.
## Sources
- `docs/voice/pipeline.md`
- `docs/voice/tracing.md`
- `src/agents/voice/pipeline.py`
- `src/agents/voice/result.py`
- `src/agents/voice/input.py`
- `src/agents/voice/model.py`
- `src/agents/voice/models/openai_stt.py`
- `tests/voice/test_pipeline.py`
- `tests/voice/test_input.py`
- `tests/voice/test_openai_stt.py`
- `tests/voice/test_openai_tts.py`
@@ -19,9 +19,15 @@ Ensure work is only marked complete after formatting, linting, type checking, an
6. If any command fails, fix the issue, rerun the script, and report the failing output.
7. Confirm completion only when all commands succeed with no remaining issues.
## Environment setup
The verification scripts assume repository dependencies are already installed. Do not run `make sync` as part of every verification pass; use it for a fresh checkout, after dependency files change, or when dependency resolution fails before the checks start.
On Linux, some Python packages with native extensions may require system packages such as `libffi-dev`, Python development headers, or build tools. If verification cannot start because one of these packages is missing, treat it as a local environment setup issue. Install the missing dependency when possible, or report the failing command and missing dependency in the PR test plan before rerunning verification in a prepared environment.
## Manual workflow
- If dependencies are not installed or have changed, run `make sync` first to install dev requirements via `uv`.
- For a fresh checkout, or if dependencies are not installed or have changed, run `make sync` first to install dev requirements via `uv`.
- Run from the repository root with `make format` first, then `make lint`, `make typecheck`, and `make tests`.
- Do not skip steps; stop and fix issues immediately when a command fails.
- If you run the steps manually, you may parallelize `make lint`, `make typecheck`, and `make tests` after `make format` completes, but you must stop the remaining steps as soon as one fails.
@@ -286,13 +286,21 @@ check_for_missing_reporters() {
log_file="${STEP_LOGS[$idx]}"
start_time="${STEP_STARTS[$idx]}"
now=$(date +%s)
wait "${pid}" 2>/dev/null || true
set +e
wait "${pid}" 2>/dev/null
step_status=$?
set -e
if [ "${step_status}" -eq 0 ]; then
finish_step "${name}" 0
return 0
fi
echo "code-change-verification: make ${name} exited before reporting completion status after $((now - start_time))s." >&2
echo "--- ${name} log (last 80 lines) ---" >&2
tail -n 80 "${log_file}" >&2 || true
stop_running_steps
return 1
return "${step_status}"
done
return 0
+10 -1
View File
@@ -8,6 +8,8 @@ description: Run python examples in auto mode with logging, rerun helpers, and b
## What it does
- Runs `uv run examples/run_examples.py` with:
- Optional dependency extras enabled by default:
`litellm`, `any-llm`, `sqlalchemy`, `redis`, `blaxel`, `modal`, `runloop`, and `temporal`.
- `EXAMPLES_INTERACTIVE_MODE=auto` (auto-input/auto-approve).
- Per-example logs under `.tmp/examples-start-logs/`.
- Main summary log path passed via `--main-log` (also under `.tmp/examples-start-logs/`).
@@ -44,6 +46,11 @@ description: Run python examples in auto mode with logging, rerun helpers, and b
.agents/skills/examples-auto-run/scripts/run.sh rerun
```
## Codex execution environment
- When Codex invokes `start` or `rerun`, run the command outside the Codex sandbox by default (`sandbox_permissions=require_escalated`). Many examples start nested sandboxes, browsers, npm helpers, or cloud/local service processes; running from inside the Codex sandbox can produce environment-only failures such as `sandbox-exec: sandbox_apply: Operation not permitted`, Playwright cache permission errors, or npm cache permission errors.
- Use sandboxed execution only when the user explicitly asks for it or when running a narrow dry-run / log inspection command that does not execute examples.
## Defaults (overridable via env)
- `EXAMPLES_INTERACTIVE_MODE=auto`
@@ -51,6 +58,7 @@ description: Run python examples in auto mode with logging, rerun helpers, and b
- `EXAMPLES_INCLUDE_SERVER=0`
- `EXAMPLES_INCLUDE_AUDIO=0`
- `EXAMPLES_INCLUDE_EXTERNAL=0`
- `EXAMPLES_UV_EXTRAS="litellm any-llm sqlalchemy redis blaxel modal runloop temporal"` (set to an empty string to disable extras)
- Auto-approvals in auto mode: `APPLY_PATCH_AUTO_APPROVE=1`, `SHELL_AUTO_APPROVE=1`, `AUTO_APPROVE_MCP=1`
## Log locations
@@ -62,7 +70,8 @@ description: Run python examples in auto mode with logging, rerun helpers, and b
## Notes
- The runner delegates to `uv run examples/run_examples.py`, which already writes per-example logs and supports `--collect`, `--rerun-file`, and `--print-auto-skip`.
- The runner delegates to `uv run --extra ... examples/run_examples.py`, which already writes per-example logs and supports `--collect`, `--rerun-file`, and `--print-auto-skip`.
- `examples/sandbox/extensions/vercel_runner.py` is temporarily excluded from auto runs due to credential issues. Do not force-run it until the credential setup is fixed.
- `start` uses `--write-rerun` so failures are captured automatically.
- If `.tmp/examples-rerun.txt` exists and is non-empty, invoking the skill with no args runs `rerun` by default.
@@ -5,6 +5,23 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)"
PID_FILE="$ROOT/.tmp/examples-auto-run.pid"
LOG_DIR="$ROOT/.tmp/examples-start-logs"
RERUN_FILE="$ROOT/.tmp/examples-rerun.txt"
DEFAULT_UV_EXTRAS="litellm any-llm sqlalchemy redis blaxel modal runloop temporal"
build_uv_prefix() {
UV_RUN=(uv run)
local extras_value
if [[ -n "${EXAMPLES_UV_EXTRAS+x}" ]]; then
extras_value="$EXAMPLES_UV_EXTRAS"
else
extras_value="$DEFAULT_UV_EXTRAS"
fi
local extra
for extra in $extras_value; do
UV_RUN+=(--extra "$extra")
done
export EXAMPLES_UV_EXTRAS="$extras_value"
}
ensure_dirs() {
mkdir -p "$LOG_DIR" "$ROOT/.tmp"
@@ -28,8 +45,9 @@ cmd_start() {
main_log="$LOG_DIR/main_${ts}.log"
stdout_log="$LOG_DIR/stdout_${ts}.log"
build_uv_prefix
local run_cmd=(
uv run examples/run_examples.py
"${UV_RUN[@]}" examples/run_examples.py
--auto-mode
--write-rerun
--main-log "$main_log"
@@ -152,7 +170,8 @@ collect_rerun() {
exit 1
fi
cd "$ROOT"
uv run examples/run_examples.py --collect "$log_file" --output "$RERUN_FILE"
build_uv_prefix
"${UV_RUN[@]}" examples/run_examples.py --collect "$log_file" --output "$RERUN_FILE"
}
cmd_rerun() {
@@ -171,8 +190,9 @@ cmd_rerun() {
export APPLY_PATCH_AUTO_APPROVE="${APPLY_PATCH_AUTO_APPROVE:-1}"
export SHELL_AUTO_APPROVE="${SHELL_AUTO_APPROVE:-1}"
export AUTO_APPROVE_MCP="${AUTO_APPROVE_MCP:-1}"
build_uv_prefix
set +e
uv run examples/run_examples.py --auto-mode --rerun-file "$file" --write-rerun --main-log "$main_log" --logs-dir "$LOG_DIR" 2>&1 | tee "$stdout_log"
"${UV_RUN[@]}" examples/run_examples.py --auto-mode --rerun-file "$file" --write-rerun --main-log "$main_log" --logs-dir "$LOG_DIR" 2>&1 | tee "$stdout_log"
local run_status=${PIPESTATUS[0]}
set -e
return "$run_status"
@@ -194,6 +214,7 @@ Commands:
Environment overrides:
EXAMPLES_INTERACTIVE_MODE (default auto)
EXAMPLES_INCLUDE_SERVER/INTERACTIVE/AUDIO/EXTERNAL (defaults: 0/1/0/0)
EXAMPLES_UV_EXTRAS (default: litellm any-llm sqlalchemy redis blaxel modal runloop; set empty to disable)
APPLY_PATCH_AUTO_APPROVE, SHELL_AUTO_APPROVE, AUTO_APPROVE_MCP (default 1 in auto mode)
EOF
}
+1 -2
View File
@@ -117,8 +117,7 @@ https://github.com/openai/openai-agents-python/compare/<tag>...<target-commit>
- <working tree status, tag/target assumptions, or re-run guidance>
```
If no risks are found, include a No material risks identified line under Risk assessment and still provide a ship call. If you did not run local verification, do not add a verification status section or use it as a release blocker; note any assumptions briefly in Notes.
If the report is not blocked, omit the `Unblock checklist` section.
If no risks are found, include a "No material risks identified" line under Risk assessment and still provide a ship call. If you did not run local verification, do not add a verification status section or use it as a release blocker; note any assumptions briefly in Notes. If the report is not blocked, omit the `Unblock checklist` section.
### Resources
@@ -38,6 +38,15 @@ Use this skill before editing code when the task changes runtime behavior or any
- If review feedback claims a change is breaking, verify it against the latest release tag and actual external impact before accepting the feedback.
- If a change truly crosses the latest released contract boundary, call that out explicitly in the ExecPlan, release notes context, and user-facing summary.
## SDK-specific decision rules
- When unsupported OpenAI API or provider-adapter behavior already has a released default path, avoid turning it into a default hard error unless the latest release boundary justifies that break. Prefer an opt-in strict mode such as `strict_feature_validation=True`, while keeping the default path compatible through warning, ignoring unsupported data, or a clearly non-empty placeholder.
- For OpenAI API feature gaps, evaluate streaming and non-streaming paths together. Custom tool calls, multi-choice Chat Completions chunks, non-text tool outputs, and similar provider payload differences must not be strict in one path and permissive or malformed in the other.
- When a change creates new public SDK behavior, do not expose it only through hard-coded module globals. Prefer an explicit public configuration object or parameter, preserve the existing default behavior when compatibility-sensitive, and make opt-in SDK defaults explicit.
- Append new optional fields or constructor parameters to public dataclasses and constructors. Do not insert them before existing public fields unless you also provide a compatibility layer and regression coverage for the old positional call shape.
- Treat threshold and quota values as part of the API design when they affect runtime behavior. Distinguish OpenAI platform quota-derived values from defensive SDK defaults; if the value is not anchored in a documented platform limit, avoid making it an unconditional default-on behavior.
- Define `None` semantics deliberately for public configuration. For example, use separate meanings for "feature disabled or no SDK limit", "use SDK default limits", and "disable only this specific limit" rather than relying on implicit truthiness checks.
## When to stop and confirm
- The change would alter behavior shipped in the latest release tag.
+211
View File
@@ -0,0 +1,211 @@
---
name: maintainer-review
description: Review a GitHub issue or pull request URL as an openai-agents-python maintainer, with a staged assessment of whether the claim is real, practically important, already solvable with supported functionality, correctly scoped, better served by another design, and worth maintainer and contributor effort. Use when assessing issue validity or severity, deciding whether an issue should be prioritized or closed, determining whether a requested feature represents an unmet need rather than a discoverability or usage gap, judging whether a PR is worth bringing to mergeable quality, comparing open PRs or alternative designs, separating code quality from repository readiness, or drafting a concise maintainer assessment. When closure, additional evidence, or code changes should be requested, also produce a polite, concise, complete, copy-paste-ready maintainer comment.
---
# Maintainer Review
## Objective
Make a maintainer decision, not a generic code-review summary. Separate these questions:
1. Is the claimed behavior real?
2. What user outcome or constraint exists independently of the reporter's proposed API or fix?
3. Can supported functionality already achieve that outcome with reasonable composition or configuration?
4. If a gap remains, is the proposed solution the best design and implementation layer?
5. Can normal users plausibly reach the gap, and what happens when they do?
6. Is it important enough to act on now?
7. If this PR did not already exist, would maintainers choose to open and implement the same work?
8. For a PR, is this solution worth merging and maintaining?
9. Can overlapping or stale operations corrupt shared state or clean up resources owned by surviving work?
10. If competing PRs exist, which single implementation path should maintainers pursue?
11. Which ambiguous scope or semantic choices are maintainer-owned product/API decisions, and what concrete direction should the contributor implement?
12. What concise maintainer message should communicate a closure or change request clearly and politely?
Treat an issue's requested field, callback, flag, class, or implementation strategy as a proposed mechanism, not as the accepted requirement. Do not begin by asking how to implement it. First prove that a concrete user outcome is not already supported and that the proposed mechanism is better than the available alternatives.
Lead with the current review state. Use `Preliminary assessment` while runtime approval or evidence is pending, and `Maintainer decision` only when the review can be concluded. Use the diff, issue narrative, or contributor effort as evidence, not as a proxy for impact.
## Workflow
### 1. Establish the exact target
- Accept a GitHub issue or PR URL as the primary input. Resolve its owner, repository, item type, and number before reviewing it.
- For an issue, read the full report, comments, reproduction, environment, linked material, and maintainer responses.
- For a PR, inspect the current remote base and head, full patch, commit history when relevant, tests, linked issue, and review discussion. Do not substitute the current local checkout for the remote change under review.
- State the claim in one falsifiable sentence. Distinguish the reported symptom from the reporter's proposed cause or fix.
- Identify the released behavior boundary when compatibility or regression claims matter.
- Verify whether linked evidence matches the PR's exact runtime variant, provider or tool type, triggering condition, and user outcome. A generic issue title, conceptual similarity, or wording such as `Related to` does not transfer evidence of need to an adjacent extension. If the reported scenario has already been fixed, treat additional variants as new needs requiring their own evidence.
Respect repository instructions for remote access and mutation. A review does not authorize comments, labels, branch changes, pushes, or other remote writes.
### 2. Establish the unmet need and challenge the proposed solution
Complete this pass before deeply evaluating a proposed implementation and before any positive issue or PR assessment.
First assign one `Need evidence` status:
- **Demonstrated**: The exact scope has a concrete supported scenario, a real-path reproduction, a released compatibility requirement, repeated demand, or a broad invariant with a meaningful consequence.
- **Plausible but unproven**: The path can exist, but realistic provider behavior, user reach, frequency, consequence, or demand is not established.
- **Already covered**: A reasonable supported workflow already satisfies the outcome.
- **Unsupported**: The outcome belongs outside the SDK contract or at a provider, adapter, or caller-owned layer.
Only `Demonstrated` need may receive `Merge-worthy as-is` or `Merge-worthy after focused changes`. For `Plausible but unproven`, prefer `Needs evidence` or `Not worth completing`; for `Already covered` or `Unsupported`, prefer closure or the relevant simpler alternative.
1. Restate the desired user outcome without naming the requested API, class, file, option, or implementation. Separate the actual constraint from the reporter's preferred mechanism.
2. Trace the closest supported ways to achieve that outcome in the current release and current target. Inspect the owning code path, public API, tests, and relevant docs rather than assuming that an unfamiliar capability is missing. Consider configuration, composition, cloning, callbacks, extension points, provider adapters, and doing the work at a caller-owned layer.
3. Determine whether the report shows a capability gap, an ergonomics or discoverability problem, an unsupported use case, or no demonstrated problem. A more convenient spelling is not automatically a missing capability.
4. Compare the proposed solution against the strongest existing approach and at least one better-design candidate: no code change, clearer documentation or validation, a narrower fix, reuse of an existing abstraction, or enforcement at a more coherent shared boundary.
5. For each viable approach, compare whether it satisfies the concrete scenario, what new public or internal contract it creates, cross-path consistency, compatibility, and permanent maintenance cost.
Do not treat a test proving that new code can work as evidence that the feature is needed. A `FakeModel` response, manually constructed provider item, mock, or new regression test can establish code-path reachability and implementation correctness; it does not by itself establish realistic provider behavior, user reach, frequency, practical consequence, or demand.
API symmetry, naming consistency, and parity with an adjacent tool, provider, or output type are design arguments, not evidence of need. Parity may justify work when it removes existing complexity or enforces a broad demonstrated invariant, but adding branches, tests, documentation, or public behavior requires independent practical justification.
If the need is not `Demonstrated`, inspect the patch only far enough to understand its contract, risk, and maintenance cost. Do not turn implementation defects, missing tests, or documentation gaps into a request-changes recommendation, because those questions become merge-blocking only after the need gate passes. If the report provides no concrete scenario, the existing functionality appears sufficient, or the requested mechanism solves only a hypothetical convenience problem, prefer `Needs evidence`, `Close`, `Supersede with a simpler alternative`, or `Not worth completing` over designing the requested feature on the reporter's behalf.
### 3. Discover competing open PRs proportionally
Do this before deeply evaluating a specified PR. A PR URL selects the starting point, not necessarily the entire comparison set.
- Determine the primary issue from explicit closing keywords, linked issues, issue timeline or development links, PR body and comments, and the reproduced symptom. If the association is inferred rather than explicit, state the evidence.
- When an issue is explicitly linked, enumerate all open PRs that address it through the issue timeline, development links, cross-references, closing keywords, and ordinary references. Include draft PRs but label them as drafts.
- When no issue is linked, run a bounded duplicate search using the strongest two or three signals from the title, reproduction, violated invariant, and runtime path. Stop when additional queries are unlikely to produce a credible competing implementation.
- Exclude closed or merged PRs from the active comparison set, while using them as history when relevant.
- Do not group PRs merely because they mention the same subsystem. Require a shared issue, symptom, violated invariant, or materially overlapping fix.
- Record the search methods and candidate set internally. If repository access cannot establish completeness, say so instead of claiming that every open PR was found. Do not list unrelated search hits in the final report.
When multiple candidates exist, compare them on need coverage, runtime correctness, scope, implementation layer, tests, compatibility, complexity, readiness, remaining maintainer work, and whether useful parts can be combined. Prefer the best maintainable solution, not the first submission or the smallest diff by default.
### 4. Use a two-stage evidence flow
Always begin with a desk review. Inspect the concrete runtime path before judging a small change as either trivial or meaningful. Check callers, adjacent helpers, validation layers, fallback paths, and existing tests. Search history or documentation only when it changes the decision. Inspecting test code is part of the desk review; executing tests, imports, examples, reproductions, benchmarks, or service calls is a runtime probe.
For repository-specific runtime invariants, start with `.agents/references/README.md` and open only the references that match the affected boundary. Treat `.agents/references/` as read-only during issue and PR review: use it to identify expected invariants, adjacent surfaces, and regression risks, then verify the current claim against the remote change, current code, tests, docs, release boundary, and focused runtime evidence. Do not edit references as a side effect of the review, infer current issue or PR status from them, or treat old issue or PR outcomes as current evidence. If the review reveals a reusable invariant that should be captured, recommend a separate repository-maintenance update unless the user explicitly asks to update references in the same task.
Use this evidence order across the two stages:
1. Trace the closest existing supported capabilities and determine whether they already satisfy the underlying user outcome.
2. Inspect existing tests and complete the code-path trace, including the mandatory interleaving and ownership pass when triggered, without executing code.
3. With explicit user approval, run a focused local reproduction of the exact claim when the desk-review rules below require it.
4. A comparison with the released version, base branch, or known-good control.
5. A broader runtime matrix only when the maintainer decision remains uncertain and the user approves it.
#### Stage 1: desk review
Produce an initial result from static evidence before running code:
##### Mandatory unmet-need and design pass
Before a positive assessment, complete the pass in step 2 and be able to state all of the following from concrete evidence:
1. The user outcome that current supported behavior cannot achieve.
2. The closest existing API or composition path and the exact reason it is insufficient.
3. Why the proposed behavior belongs at the chosen abstraction layer instead of a caller, adapter, validation, documentation, or existing extension point.
4. Why the proposed permanent contract is better than no code change and the strongest narrower alternative.
5. What real scenario, compatibility requirement, or repeated demand justifies the new maintenance surface.
6. Whether maintainers would choose to pursue the same work if no contributor had already supplied a patch.
If any answer is missing and could change whether code should exist at all, do not call the issue actionable or the PR merge-worthy. Request only the evidence needed to distinguish a genuine capability gap from a usage, discoverability, or solution-design problem. This is a product and architecture evidence gap, not a runtime-probe trigger by itself.
##### Mandatory interleaving and ownership pass
Run this pass before any positive PR assessment when a patch adds, removes, or reorders cleanup, retry, reconnect, cancellation, listeners, shared futures or tasks, connections or streams, state flags, or mutable state across an `await`, callback, event, or deferred completion.
1. Name each shared resource or state value and the operation that owns it. Include listeners, futures, tasks, connections, streams, locks, caches, state flags, persistence, and telemetry.
2. Trace at least two overlapping operations, `A` and `B`, across every suspension or re-entry point. Check `A pending -> B starts -> A fails -> B succeeds`, `A pending -> B starts -> B fails -> A succeeds`, close or cancellation between setup and completion, and a stale completion arriving after newer work.
3. For every cleanup or rollback, identify the exact attempt and resource generation it is allowed to dispose. Treat unconditional cleanup after a suspension point as a regression candidate until the code proves it cannot tear down newer or surviving work.
4. Compare base and head for the survivor invariant. Replacing duplicated work with missing handlers, a closed shared resource, reverted state, or a failed surviving task is a regression, not successful cleanup.
5. Inspect tests for controlled interleavings using deferred futures, callbacks, or events. Require assertions about the surviving operation's observable behavior and final resource state, not only listener counts or individual exception results.
Do not mark a concurrency-sensitive patch `Merge-worthy as-is` merely because sequential reconnect, retry, failure, and close tests pass. If the code trace proves an unsafe interleaving, conclude from static evidence and request a focused fix and regression test. If ownership remains ambiguous, keep the result preliminary and request approval for the smallest decisive runtime probe.
- If the claim or PR is decisively negative from a complete reachable code-path trace, conclude the review without a runtime probe. Examples include an impossible or unsupported path, duplicated existing handling, a demonstrated no-op, a direct compatibility break, or a clearly wrong abstraction. Do not call an ambiguous result negative merely to avoid a probe.
- If the initial result is positive and there is no unresolved runtime concern, and any triggered interleaving and ownership pass is complete, the desk review may be sufficient for a final maintainer decision. Do not run a probe only to restate evidence that cannot plausibly change the decision.
- If the initial result is positive but there is any unresolved runtime concern that could plausibly change claim validity, severity, merge-worthiness, required changes, or the preferred competing PR, stop before executing code. Report a `Preliminary assessment`, name the concern, propose the smallest decisive probe and control, and ask the user for approval to run it.
- A purely stylistic, documentation, CI-status, or repository-readiness concern does not trigger a runtime probe unless it masks a runtime question.
Do not issue a definitive positive maintainer decision while a decision-relevant runtime concern remains unresolved. If the user declines the probe, keep the result preliminary and state the exact confidence limitation.
#### Stage 2: approved runtime probe
After explicit approval, run only the smallest probe needed to resolve the stated concern. Exercise the real public or internal path and include a base, release, or known-good control when relevant. Do not stop at a happy-path smoke check when failure behavior determines the decision. Return to the user for separate approval before expanding materially beyond the approved probe.
For latency, timeout, buffering, backpressure, or cleanup claims, measure at least one observable elapsed-time or state-transition path when feasible. Do not assume that a mocked unit test exercises real scheduling or provider behavior. Prefer a local probe first; use an approval-gated live-service probe only when local evidence cannot settle the decision.
Use `$runtime-behavior-probe` only when the user explicitly invokes it and the skill is available, or when the user explicitly approves using it for the proposed runtime work. Preserve its environment-variable approval, live-service, cost, cleanup, and reporting gates. Do not make ordinary maintainer review depend on that skill being available.
For changes involving validation, fail-fast behavior, cleanup, retries, interruption, or concurrency, trace lifecycle ordering in addition to the main behavior:
- Identify listeners, tasks, connections, files, locks, state mutations, and other resources acquired before the new check or failure point.
- Verify cleanup when construction, context-manager entry, validation, connection, or execution raises before normal teardown runs.
- Require a negative-path test when a failure can leave observable state or resources behind.
Do not over-investigate. Stop when additional evidence is unlikely to change validity, severity, or the maintainer recommendation.
### 5. Calibrate validity and impact
Use `references/evaluation-framework.md` to assess claim validity, realistic reach, consequence, breadth, frequency, recoverability, compatibility, and severity. Keep observed facts separate from inference and state any missing evidence that could change the decision.
Report the `Need evidence` status before classifying the need as a capability gap, ergonomics or discoverability gap, unsupported use case, or no demonstrated gap. Do not assign practical impact to the absence of the requested mechanism when an existing supported workflow already produces the requested outcome. Do not infer practical importance merely from reachability, API asymmetry, or a technically successful patch.
For a PR, make `Severity` describe the underlying issue or user need only. Do not combine it with the risk created by the proposed patch. Report a meaningful patch-induced regression, compatibility, lifecycle, or maintenance risk separately as `Patch risk`.
Do not infer that a report is low-value merely because an AI may have found or written it. Do not speculate about authorship or motive. Identify contribution-shaped reports through objective signals: no reproducible behavior, unrealistic inputs, an impossible call path, duplicated existing handling, tests that do not exercise the claim, or a fix whose runtime result is a no-op.
### 6. Apply the maintainer-effort test
Use the framework's issue dispositions and PR checks to decide whether the outcome justifies permanent code, tests, documentation, and maintainer attention. Classify code quality separately from repository readiness.
Use one code recommendation:
- **Merge-worthy as-is**: real need, sound implementation, proportionate scope, adequate tests.
- **Merge-worthy after focused changes**: real need and viable direction, with bounded corrections.
- **Supersede with a simpler alternative**: real need, but a smaller or more coherent fix is preferable.
- **Not worth completing**: negligible or unsupported impact, no-op behavior, wrong abstraction, or excessive completion cost.
`Merge-worthy as-is` and `Merge-worthy after focused changes` are invalid unless `Need evidence` is `Demonstrated`. A bounded set of implementation fixes cannot promote a `Plausible but unproven` need into a merge-worthy recommendation.
For `Merge-worthy as-is` and `Merge-worthy after focused changes`, use one repository-readiness status when it helps communicate the integration state:
- **Ready**: current head is reviewable and required checks are green.
- **CI or review pending**: code recommendation is stable, but required external gates are incomplete.
- **Rebase or conflict resolution required**: the head cannot merge cleanly or is materially stale.
- **Blocked**: a concrete external or repository condition prevents a reliable merge decision.
Omit repository readiness for `Supersede with a simpler alternative` and `Not worth completing`; CI, review, mergeability, or branch freshness does not change those dispositions. Put any validation limitation that materially affects confidence in the evidence instead. When readiness is included, use exactly one of the four statuses above and do not invent variants such as `ready mechanically` or use rebase status for semantic staleness.
Do not downgrade an otherwise sound code recommendation solely because CI is pending. Do not call a PR ready when semantic conflict resolution or material code changes remain.
When multiple open PRs address the same issue, make one portfolio-level recommendation: select the strongest PR, request focused changes in one candidate, combine specific ideas into one PR, supersede all candidates with a simpler approach, or close duplicates. Explain why the recommended path is better than each alternative without turning the report into line-by-line review.
Always compare the proposed patch with the strongest existing supported approach and at least one alternative: no code change, validation or documentation, a narrower fix, reuse of an existing helper, or a different layer that enforces the invariant consistently. A review is incomplete if it establishes only that the patch works without establishing why the current product cannot meet the underlying need and why this design is preferable.
When multiple plausible semantic scopes, compatibility boundaries, or public API contracts remain, do not ask the contributor to choose among maintainer-owned options. Decide the preferred scope from the evidence, compatibility contract, and product/API design principles, then request that specific change. If the evidence is insufficient to choose, mark the review preliminary or request maintainer input; do not present an open-ended implementation fork as the contributor's decision.
### 7. Report findings and maintainer action
Choose the assessment language using this precedence:
1. Follow an explicit language request in the current conversation.
2. Follow an applicable language instruction from `~/.codex/AGENTS.md`, the repository's `AGENTS.md`, or another governing instruction file.
3. If recent conversation turns are consistently in one language, use that language.
4. Otherwise, default to English.
Do not infer the assessment language from the GitHub URL, contributor, code, or browser locale. Maintainer comment drafts remain English regardless of the assessment language. Keep the report decision-oriented and compact. Use no more than five evidence bullets by default; add more only when the decision genuinely depends on them.
Use the matching compact report variant in `references/evaluation-framework.md`. While runtime approval is pending, use its preliminary-assessment variant and end with the approval request instead of presenting a final recommendation. Collapse sections for simple cases rather than padding the answer. Put unexpected or negative runtime findings first, and name the preferred PR or approach explicitly when candidates compete.
For PRs, put `Need evidence` before code recommendation. When the need is not `Demonstrated`, lead with that result, omit repository readiness, and avoid presenting patch fixes as the primary maintainer action.
When existing functionality or a better alternative materially affects the decision, state it explicitly in the evidence and recommendation. Name the exact supported path, what it does and does not cover, and why it is preferable. Do not bury a `Not worth completing` or `Supersede with a simpler alternative` conclusion beneath praise for implementation quality.
When recommending closure, requesting more evidence, requesting code changes, or superseding a PR, append the English, copy-paste-ready maintainer comment defined by the framework. If multiple PRs need different actions, label one draft for each affected PR. Include only merge-blocking requests in the main action paragraph; keep optional documentation or polish clearly non-blocking or omit it.
For request-changes comments, phrase maintainer-owned semantic decisions as a directive, not as a menu. It is fine to mention the rejected alternative briefly in the rationale, but the requested action must identify the chosen behavior, scope, or compatibility boundary. Use "please do X because..." instead of "either do X or Y" when X versus Y changes the SDK contract or user-visible semantics.
Do not produce a line-by-line review unless requested. Do not equate passing tests with merge-worthiness, or a logically correct patch with practical value.
## Resource
- `references/evaluation-framework.md` contains the severity rubric, evidence checks, lifecycle review, issue dispositions, PR quality checks, maintainer-comment guidance, and report variants.
@@ -0,0 +1,4 @@
interface:
display_name: "Maintainer Review"
short_description: "Gate PR value on demonstrated user need"
default_prompt: "Use $maintainer-review with this GitHub issue or PR URL. Before evaluating implementation quality, verify that linked evidence matches the exact runtime variant and assign Need evidence as Demonstrated, Plausible but unproven, Already covered, or Unsupported. Only a Demonstrated need may receive a merge-worthy recommendation; synthetic tests, API parity, and contributor effort do not establish need. Then compare existing and alternative approaches, complete the desk review and required lifecycle ownership checks, request approval before any decision-relevant runtime probe, compare credible competing PRs, recommend the best maintainer action, and include an English comment draft when closure or changes are needed."
@@ -0,0 +1,366 @@
# Maintainer Evaluation Framework
Use this reference when a claim is ambiguous, severity is disputed, or a PR is technically correct but may not justify merge effort.
## Contents
- [Decision model](#decision-model)
- [Severity rubric](#severity-rubric)
- [Evidence-strength checks](#evidence-strength-checks)
- [Unmet need and alternative design gate](#unmet-need-and-alternative-design-gate)
- [Issue disposition](#issue-disposition)
- [PR quality and value](#pr-quality-and-value)
- [Documentation threshold](#documentation-threshold)
- [Lifecycle and failure-path review](#lifecycle-and-failure-path-review)
- [Concurrency and cleanup ownership](#concurrency-and-cleanup-ownership)
- [Better-alternative prompts](#better-alternative-prompts)
- [Competing PR comparison](#competing-pr-comparison)
- [Maintainer comment drafts](#maintainer-comment-drafts)
- [Compact report variants](#compact-report-variants)
## Decision model
Treat validity, severity, and merge-worthiness as separate results. Also distinguish a `Preliminary assessment`, which may still require approved runtime evidence, from a final `Maintainer decision`. Do not label a provisional positive result as a verdict or final decision.
| Dimension | Questions | Strong evidence |
|---|---|---|
| Claim validity | Does the exact reported behavior occur? Is the proposed cause correct? | Reproduction, failing focused test, or complete reachable code path |
| Reachability | Can supported, realistic inputs reach it? | Public API trace, real configuration, linked user report, or release comparison |
| Consequence | What fails, and is the result silent or recoverable? | Observed output/error/state plus downstream effect |
| Breadth | Who is affected? | Supported providers, platforms, versions, and configurations identified precisely |
| Frequency | Is this normal, intermittent, or pathological? | Repeat runs, telemetry or reports when available, deterministic preconditions |
| Need evidence | Is the exact scope demonstrated, merely plausible, already covered, or unsupported? | Same-scope user scenario, real-path reproduction, released compatibility requirement, repeated demand, or broad consequential invariant |
| Unmet need | What user outcome cannot be achieved through supported behavior today? | Concrete scenario plus a trace showing why the closest existing path is insufficient |
| Existing capability | Can configuration, composition, cloning, callbacks, extension points, or a caller-owned layer already satisfy the outcome? | Current release code, tests, docs, and an exact supported workflow |
| Compatibility | Is released behavior or durable state changed? | Latest release comparison and explicit contract inspection |
| Solution fit | Is the requested mechanism the best design and implementation layer? | Proposed solution compared with the strongest existing path and at least one narrower or more coherent alternative |
| Maintainer-owned scope | When several plausible semantics remain, which behavior should the SDK own? | A concrete maintainer decision grounded in compatibility, user outcome, and API design, not an open-ended contributor choice |
| Resource ownership | Can stale, failed, cancelled, or overlapping work mutate or clean up resources owned by surviving work? | Interleaving trace, attempt or generation ownership, and survivor assertions |
| Maintenance cost | What permanent complexity and review burden does it add? | Changed surface, new branches/configuration, test burden, remaining work |
## Severity rubric
- **Negligible**: No runtime difference, unreachable or unsupported input, cosmetic inconsistency, or a fully harmless edge case. Usually close, document, or decline code complexity.
- **Low**: Real but narrow and recoverable behavior with a simple workaround and no data, security, or compatibility risk. Merge only when the fix is small and clearly improves an invariant.
- **Moderate**: Plausible supported use fails or produces incorrect behavior for a meaningful subset of users. Prioritize a bounded fix and regression test.
- **High**: Common or important supported use is broken, causes serious compatibility problems, leaks sensitive data, or risks persistent corruption. Treat as urgent and require strong validation.
- **Critical**: Broadly exploitable security impact, severe data loss, or systemic failure requiring immediate coordinated action. Use only with concrete evidence.
Severity is approximately consequence multiplied by realistic reach and frequency, reduced by recoverability. Do not raise severity because a report sounds alarming or lower it because a patch is small.
## Evidence-strength checks
Before calling a claim confirmed, answer:
- Does the reproduction exercise the same public or internal path named in the report?
- Does the failure still occur on the relevant base, release, or current target?
- Does the test fail without the patch and pass with it?
- Are setup failures, stale builds, environment leakage, proxies, caches, or unsupported options excluded?
- Does an adjacent helper or equivalent path follow different semantics?
- Is the observed behavior prohibited by an actual contract, or merely surprising?
- For latency, timeout, buffering, backpressure, or cleanup claims, was observable elapsed time or a real state transition measured when feasible rather than inferred only from mocks?
- For shared asynchronous state, do tests control completion order and prove that stale failure or cleanup cannot affect the surviving operation?
Use `partially confirmed` when the symptom is real but the cause, reach, or claimed scope is wrong. Use `unproven` when decisive evidence is missing. Use `contradicted` only when evidence directly disproves the claim.
## Unmet need and alternative design gate
Issue reports often combine a desired outcome with a proposed API or implementation. Treat the proposed mechanism as a hypothesis. Confirm the unmet outcome before evaluating how well the patch implements that mechanism.
### Linked-evidence scope
Evidence from a linked issue applies only when the issue and PR share the same runtime variant, provider or tool type, trigger, supported configuration, and user outcome. A broad title, ordinary reference, `Related to` statement, or conceptual similarity is not enough. If an earlier change already resolved the concrete reported scenario, an adjacent extension starts with no inherited evidence of need.
### Need evidence status
Assign one status before deep implementation review:
- **Demonstrated**: The exact scope has a concrete supported scenario, real-path reproduction, released compatibility requirement, repeated demand, or broad invariant with meaningful consequence.
- **Plausible but unproven**: The code path is possible, but realistic reach, frequency, consequence, provider behavior, or demand is missing.
- **Already covered**: A reasonable supported workflow already satisfies the outcome.
- **Unsupported**: The outcome is outside the SDK contract or belongs at a provider, adapter, or caller-owned layer.
Only `Demonstrated` need can support a merge-worthy code recommendation. `Plausible but unproven` maps to `Needs evidence` or `Not worth completing`, even when the patch is technically correct and its remaining fixes are bounded. `Already covered` and `Unsupported` normally map to closure or a simpler non-core alternative.
Before accepting an issue or recommending a PR, record:
| Question | Required evidence |
|---|---|
| What outcome is needed? | A concrete supported scenario stated without the proposed API or fix |
| What exists today? | The closest current-release API, configuration, composition, extension point, or caller-owned solution |
| Why is it insufficient? | An exact behavioral, compatibility, lifecycle, or operational constraint, not preference alone |
| What are the alternatives? | The proposed patch, the strongest existing path, and at least one no-code, narrower, or better-layer design |
| Why add a contract? | Practical benefit sufficient to justify public surface, runtime branches, cross-path tests, documentation, and long-term maintenance |
Classify the result:
- **Capability gap**: a supported, realistic outcome cannot be achieved with current functionality. Code may be warranted.
- **Ergonomics or discoverability gap**: the outcome is already possible, but the supported route is confusing or unnecessarily difficult. Prefer documentation, validation, or a narrowly justified convenience improvement.
- **Unsupported use case**: the desired outcome lies outside the SDK contract or belongs at a provider, adapter, application, or other caller-owned layer. Do not expand the core API merely to make it possible.
- **No demonstrated gap**: no concrete scenario proves that existing functionality is insufficient. Request evidence or close rather than designing from the proposed mechanism.
Passing tests for a new implementation establish feasibility and correctness, not need. A `FakeModel` response, manually constructed provider item, mock, or synthetic fixture does not establish realistic provider behavior, user reach, frequency, consequence, or demand. API symmetry and parity with an adjacent runtime are design arguments, not need evidence. A technically coherent patch can still be `Not worth completing` when the motivating scenario is hypothetical, already supported, or better solved elsewhere.
Use the counterfactual maintainer test: if the PR did not already exist, would maintainers choose to file and implement the same work from the available evidence? Contributor effort lowers implementation cost but does not create product need or remove permanent maintenance cost.
When the need is not `Demonstrated`, inspect implementation only far enough to estimate contract, risk, and maintenance cost. Do not convert patch defects, missing tests, or documentation gaps into a request-changes disposition; those become merge blockers only after the need gate passes.
## Issue disposition
Choose one primary action:
- **Prioritize**: confirmed moderate-or-higher impact or an important invariant with no safe workaround.
- **Accept, low priority**: confirmed low impact, existing supported functionality is insufficient for the demonstrated scenario, and a proportionate fix appears possible.
- **Narrow scope**: a valid core exists, but the report overstates affected paths or expected behavior.
- **Needs evidence**: plausible claim, but no minimal reproduction, supported setup, contract basis, or concrete scenario showing why existing functionality is insufficient.
- **Close**: duplicate, unsupported, unreachable, contradicted, no-op, already addressed by a reasonable supported path, or not worth permanent complexity.
When requesting evidence, ask only for information that could change the disposition.
## PR quality and value
Assess these independently:
1. **Need**: Same-scope issue or runtime evidence demonstrates a concrete unmet user outcome that the closest supported capability cannot reasonably satisfy. Do not inherit evidence from an adjacent variant or already-fixed scenario.
2. **Correctness**: The fix works for the reported case and meaningful boundaries.
3. **Placement**: The invariant is enforced once at the right layer instead of duplicating existing functionality, patching locally, or moving caller- or provider-owned policy into the core SDK.
4. **Consistency**: Equivalent sync/async, streaming/non-streaming, provider, serialization, and resume paths remain aligned where applicable.
5. **Tests**: A regression test fails on the base, passes on the head, and tests the exact non-happy-path value or state. When shared state crosses an asynchronous boundary, tests control relevant completion orders and assert the surviving operation's behavior and final resource state.
6. **Compatibility**: Released positional APIs, wire formats, persisted schemas, and established error behavior are preserved or intentionally migrated.
7. **Proportionality**: Complexity and public surface are justified by impact.
8. **Completion cost**: Remaining fixes, docs, tests, and design work are bounded enough to justify maintainer attention.
A PR can be correct but not merge-worthy. Typical reasons include a nonexistent or negligible need, an outcome already supported through a reasonable existing mechanism, a no-op on the actual runtime path, incomplete cross-path semantics, an abstraction cost larger than the benefit, or a simpler design at another layer.
Do not use implementation correctness, bounded remaining work, CI status, or contributor effort to upgrade a need that is only `Plausible but unproven`. Merge-worthiness is gated by demonstrated need, not by how close the patch is to completion.
Keep issue impact and patch risk separate. `Severity` describes the underlying issue or user need. A regression, compatibility break, lifecycle leak, or maintenance hazard introduced by the proposed patch belongs under `Patch risk` and must not inflate or obscure the issue severity.
When a PR exposes an ambiguous semantic boundary, decide whether that boundary belongs to maintainers before drafting requests. If the choice affects SDK contract, compatibility, persistence, error semantics, public API meaning, or cross-path behavior, the review should pick one direction or explicitly block on maintainer input. Do not delegate that choice to the contributor as "either X or Y"; ask for the chosen behavior and the tests or docs needed to lock it down.
## Documentation threshold
Do not treat documentation as automatically required for every public option, constructor parameter, provider setting, or behavior change. Make docs merge-blocking only when at least one of these is true:
- Existing user-facing docs become materially false, unsafe, or misleading.
- Correct or safe use depends on a non-obvious constraint, migration step, compatibility boundary, or operational warning.
- Repository policy, the accepted issue scope, or an explicit maintainer decision requires documentation in the same PR.
- The intended feature would be practically unusable or undiscoverable by its target users without a documented entry point, and generated API reference or clear code-level discovery is insufficient.
If docs would merely improve discoverability or completeness, keep them non-blocking. Do not change `Merge-worthy as-is` to `Merge-worthy after focused changes` solely for optional docs, and do not include optional docs in the maintainer comment's required-action paragraph. Respect an explicit maintainer choice to omit docs or defer them to a separate follow-up.
## Lifecycle and failure-path review
Apply this section when a change adds validation, fail-fast behavior, cleanup, retries, interruption, background work, or concurrency.
- Identify the earliest point where all dynamic inputs needed for a correct decision are available.
- List side effects before and after that point: listeners, tasks, connections, files, locks, caches, state mutations, and telemetry.
- Exercise failure during construction, context-manager entry, validation, connection, and execution when those phases exist.
- Confirm that normal teardown is actually entered. If an enter or constructor fails, verify cleanup explicitly rather than assuming an exit hook runs.
- Prefer validation after dynamic configuration is resolved but before avoidable side effects begin.
- Require a regression test for any listener, task, connection, or state that could remain after failure.
## Concurrency and cleanup ownership
Apply this section before a positive assessment whenever lifecycle work crosses an `await`, callback, event, deferred completion, retry, reconnect, cancellation, or shared resource boundary. Sequential correctness is insufficient because a patch can improve isolated cleanup while introducing cross-attempt teardown.
Use a two-operation interleaving matrix during desk review:
| Ordering | Required question |
|---|---|
| `A pending -> B starts -> A fails -> B succeeds` | Can A's cleanup remove or revert anything B needs? |
| `A pending -> B starts -> B fails -> A succeeds` | Can B's cleanup leave A successful but non-functional? |
| `A succeeds -> B starts -> stale A completion` | Can stale A overwrite B's newer state or generation? |
| setup -> close/cancel -> late completion | Can late work resurrect listeners, state, tasks, or connections after teardown? |
For each ordering:
- Identify the resource owner before and after every suspension point.
- Distinguish per-attempt resources from shared runner, session, transport, cache, or listener state.
- Require cleanup to carry an ownership token, generation, identity check, serialization guarantee, or another invariant that prevents cross-attempt disposal.
- Compare base and head on the survivor invariant. Fewer duplicates do not justify losing the only active handler, connection, task, or state update.
- Require a controlled interleaving test when the ordering is reachable. The test must assert both the failing operation and the surviving operation's observable behavior after all completions settle.
An unscoped `finally`, `except`, close handler, cancellation callback, or rollback that mutates shared state after a suspension point is merge-blocking when another operation can still own or use that state.
## Better-alternative prompts
Start with the strongest existing supported path, then test at least one additional alternative against the proposed patch. Do not complete a positive review without this comparison.
- Can the requested outcome already be achieved through configuration, composition, cloning, callbacks, extension points, a custom provider or adapter, or caller-owned code?
- If the existing route is awkward, is the problem discoverability or ergonomics rather than missing capability?
- What happens if maintainers make no code change?
- Can input validation or an existing helper enforce the invariant earlier?
- Can the fix be limited to the one supported path that fails?
- Would documentation or a clearer error prevent misuse without runtime complexity?
- Can the test be added first to reveal the smallest correct change?
- Is the proposed public option compensating for an internal design issue?
- Is the proposed core behavior actually provider- or application-specific policy that belongs at another layer?
## Competing PR comparison
When two or more open PRs address the same issue, first verify that they belong in one comparison set. Accept an explicit issue link, the same minimal reproduction, the same violated invariant, or materially overlapping runtime paths as association evidence. Do not treat a shared label or subsystem as sufficient.
Compare each candidate on the same evidence basis:
| Criterion | Question |
|---|---|
| Need | Does a concrete user outcome remain unmet after tracing existing supported functionality? |
| Existing capability | Could every candidate be avoided by configuration, composition, an extension point, or a better caller- or provider-owned solution? |
| Coverage | Does it solve the whole confirmed issue, a useful subset, or an adjacent problem? |
| Correctness | Does the fix work on the real path and meaningful boundaries? |
| Placement | Does it enforce the invariant at the correct shared layer? |
| Tests | Does it reproduce the base failure and distinguish the candidate approaches? |
| Compatibility | Does it preserve released APIs, state, protocol, providers, and established behavior? |
| Complexity | What permanent branches, abstractions, configuration, or coupling does it add? |
| Readiness | Is it mergeable now, or how much focused work remains? |
| Reuse | Are there valuable tests or implementation pieces that should be combined into another candidate? |
Choose one portfolio-level disposition:
- **Prefer one PR**: identify the strongest candidate and close or supersede duplicates.
- **Prefer one after focused changes**: keep one candidate active and state bounded changes required before merge.
- **Combine selectively**: identify the destination PR and the exact ideas or tests worth transferring; avoid asking maintainers to reconcile entire competing implementations.
- **Replace all**: explain the simpler or more coherent implementation that should supersede every candidate.
- **Merge none**: the issue is invalid, negligible, unsupported, or none of the approaches justify completion cost.
Do not split the decision into independent approvals. Competing PRs consume overlapping review and maintenance budgets, so recommend one path for the issue as a whole.
## Maintainer comment drafts
Always write maintainer comments in English, regardless of the assessment language. Produce a draft when the recommendation is to close, request evidence, request focused code changes, supersede a PR, or choose one competing PR over another.
Keep each draft polite, direct, and copy-paste-ready. Usually use 60-160 words in one to three short paragraphs:
1. Acknowledge the contribution or report.
2. Explain the decision with the smallest amount of decisive technical evidence.
3. Give the exact next action or the condition for reconsideration.
Do not include internal labels such as `severity: low`, speculate about AI authorship or contributor intent, repeat the full review, or soften the message until the requested action becomes unclear.
Do not ask contributors to choose maintainer-owned semantics. If two implementations are technically possible but one changes the SDK contract, decide the contract in the review and make the comment actionable. Use a short rationale such as "This keeps the new handler scoped to the existing raise site" or "This makes the handler name match all invalid final messages", then request the exact code and tests for that decision.
### Close
```text
Thanks for taking the time to investigate this. I traced the reported case through <path or behavior>, and <decisive finding>. In the supported path, <practical result>, so the added complexity is not justified by the demonstrated impact.
I am going to close this <issue/PR>. If you can provide <specific reproduction or evidence that would change the decision>, we can revisit the underlying problem with that narrower scope.
```
### Request changes
```text
Thanks for the contribution. The underlying issue is valid, and this approach is directionally reasonable. Before we can merge it, please address the following points: <bounded list of required changes>.
These changes are needed because <concise contract, lifecycle, compatibility, or test reason>. Once they are covered with a regression test that fails on the base and passes on the updated branch, the PR should be ready for another review.
```
Adapt the wording to the actual evidence. Do not use these templates as generic filler.
### Existing capability or better alternative
```text
Thanks for the contribution. I traced the underlying use case through <existing API or workflow>, which already supports <desired outcome and relevant limits>. The proposed change adds <new contract or complexity>, but the issue does not demonstrate a concrete supported case that the existing approach cannot handle.
I am going to close this <issue/PR> for now. If you can provide <specific scenario showing the existing approach is insufficient>, we can revisit the unmet need and choose the narrowest appropriate design from that evidence.
```
## Compact report variants
Use `Maintainer decision` for a concluded review. Use `Preliminary assessment` when a desk review is tentatively positive but a decision-relevant runtime concern remains. `Verdict` is intentionally avoided in the report headings because it does not communicate whether the result is provisional or final.
### Runtime approval gate
```markdown
## Preliminary assessment
<Tentative issue or PR assessment based on desk review only.>
## Static evidence
- <decisive code-path or test-inspection evidence>
- <what remains uncertain at runtime>
## Proposed runtime probe
- Concern: <the uncertainty that could change the decision>
- Probe: <smallest exact execution path>
- Control: <base, release, or known-good comparison when relevant>
- Scope: <local-only or any live-service, cost, mutation, or cleanup implications>
## Approval request
<Ask whether to run this exact probe. Do not present a final positive recommendation yet.>
```
### Issue
```markdown
## Maintainer decision
<Real/partial/unproven/contradicted, severity, and disposition.>
## Evidence
- <decisive evidence>
- <scope or uncertainty>
## Existing capability and alternatives
<Closest supported path, why it is or is not sufficient, and the preferred design alternative.>
## Recommendation
<Prioritize, accept low priority, narrow, request evidence, or close.>
## Maintainer comment draft
<Include when closure or additional evidence should be requested.>
```
### Pull request
```markdown
## Maintainer decision
<Need, practical impact, and merge-worthiness.>
- Need evidence: <Demonstrated / Plausible but unproven / Already covered / Unsupported>
- Code recommendation: <code disposition>
- Repository readiness: <integration status; include only for a merge-worthy recommendation when material>
## Evidence
- <runtime or code-path result>
- <test and compatibility result>
## Existing capability and alternatives
<Closest supported path, why the demonstrated scenario cannot use it, and why this patch is preferable to no code change or a narrower design.>
## Issue impact
- Validity: <claim validity>
- Severity: <severity of the underlying issue or need>
- Reach: <realistic reach>
## Patch risk
<Include only when the proposed patch introduces a meaningful regression, compatibility, lifecycle, or maintenance risk.>
## PR quality
- Solution fit: <assessment>
- Tests: <assessment>
- Remaining effort: <bounded/unbounded and why>
## Recommendation
<Merge, focused changes, simpler replacement, or close.>
## Maintainer comment draft
<Include only when closure, evidence, or changes should be requested.>
```
### Competing pull requests
```markdown
## Maintainer decision
<Issue validity, practical severity, and preferred implementation path.>
## Open PR comparison
| PR | Approach | Correctness | Tests | Compatibility/complexity | Readiness |
|---|---|---|---|---|---|
| #... | ... | ... | ... | ... | ... |
## Recommendation
<Select one, request focused changes, combine specific parts, replace all, or merge none.>
<State what should happen to every other open candidate.>
## Maintainer comment drafts
<One copy-paste-ready draft for each PR that should be closed, changed, or superseded.>
```
+5 -4
View File
@@ -1,16 +1,17 @@
---
name: pr-draft-summary
description: Create the required PR-ready summary block, branch suggestion, title, and draft description for openai-agents-python. Use in the final handoff after moderate-or-larger changes to runtime code, tests, examples, build/test configuration, or docs with behavior impact; skip only for trivial or conversation-only tasks, repo-meta/doc-only tasks without behavior impact, or when the user explicitly says not to include the PR draft block.
description: Create the required PR-ready summary block, branch suggestion, title, and draft description for openai-agents-python. Use before the final response whenever the current task changed runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size and including local-only or uncommitted work. Skip only for trivial or conversation-only tasks, repo-meta/doc-only tasks without behavior impact, or when the user explicitly says not to include the PR draft block.
---
# PR Draft Summary
## Purpose
Produce the PR-ready summary required in this repository after substantive code work is complete: a concise summary plus a PR-ready title and draft description that begins with "This pull request <verb> ...". The block should be ready to paste into a PR for openai-agents-python.
Produce the PR-ready summary required in this repository after eligible code work is complete: a concise summary plus a PR-ready title and draft description that begins with "This pull request <verb> ...". The block should be ready to paste into a PR for openai-agents-python.
## When to Trigger
- The task for this repo is finished (or ready for review) and it touched runtime code, tests, examples, docs with behavior impact, or build/test configuration.
- Treat this as the default final handoff step for substantive code work. Run it after any required verification or changeset work and before sending the "work complete" response.
- Before every final response, check whether the current task changed runtime code (`src/agents/`), tests (`tests/`), examples (`examples/`), build/test configuration, or docs with behavior impact.
- If it did, run this skill after required verification and before sending the final response. Do not use perceived change size to decide whether to run it.
- Run it for eligible local-only and uncommitted work even when the user did not ask to create a pull request. Producing this text does not authorize creating a branch, committing, pushing, or opening a pull request.
- Skip only for trivial or conversation-only tasks, repo-meta/doc-only tasks without behavior impact, or when the user explicitly says not to include the PR draft block.
## Inputs to Collect Automatically (do not ask the user)
@@ -24,6 +24,7 @@ Use this skill to investigate real runtime behavior, not to restate code or docu
- Use temporary files or a temporary directory for one-off probe scripts.
- Keep temporary artifacts until the final response is drafted. Then delete them by default unless the user asked to keep them or they are needed for follow-up. Even when artifacts are deleted, keep a short run summary of the command shape, runtime context, and artifact status in the report.
- Before executing a live probe that will read environment variables, tell the user the exact variable names you plan to use and why, then wait for explicit approval. Examples include `OPENAI_API_KEY` and other expected default names for the system under test.
- When the environment-variable approval gate is required and the `request_user_input` tool is available, use that tool instead of a plain-text approval question. Ask one concise question with mutually exclusive choices such as `Allow once (Recommended)` and `Do not allow`, omit `autoResolutionMs`, and make the approval single-probe and limited to the exact named variables and destination. If the tool is unavailable, fall back to a concise plain-text approval question and do not proceed until the user explicitly approves.
- Never print secrets, even when they come from standard environment variables that this skill may use.
- For OpenAI API or OpenAI platform probes in this repository, use [$openai-knowledge](../openai-knowledge/SKILL.md) early to confirm contract-sensitive details such as supported parameters, field names, and limits. Use runtime probing to validate or challenge the documented behavior, not to skip the documentation pass entirely. If the docs MCP is unavailable, fall back to the official OpenAI docs and say that you used the fallback in the report.
- For benchmark or comparison probes, make parity explicit before execution. Record what is held constant, what variable is under test, which response-shape constraints keep the comparison fair, and any usage or token counters that matter for interpreting latency or cost.
@@ -51,7 +52,7 @@ Use this skill to investigate real runtime behavior, not to restate code or docu
7. For comparative probes, define parity before execution. Record prompt or input shape, tool-choice setup, model-settings parity, state reuse rules, and any response-shape constraint that keeps the comparison fair. If materially different output length could bias the result, record usage or token notes too.
8. If the question asks whether one option has the same intelligence or quality as another, decide whether the matrix supports only example-pattern parity or a broader quality claim. For broader claims, add at least one harder or more open-ended case. Otherwise say explicitly that the result is limited to the covered patterns.
9. Plan state controls before execution when hidden state could affect the result. Record whether each case uses fresh or reused state, how cache reuse or cache busting is handled, what unique IDs isolate repeated runs, and how cleanup is verified.
10. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.
10. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Prefer `request_user_input` for this gate when it is available, with no auto-resolution and choices that grant or deny only this specific probe. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.
11. Build task-specific probe scripts in a temporary location. Keep the script small, observable, and easy to discard.
12. In `openai-agents-python`, make the runtime context explicit:
- Run Python probes from the repository root with `uv run python` when practical.
@@ -27,6 +27,17 @@ Do not read these variables automatically. Before a live probe uses any of them,
If the task targets another standard integration, use that integration's expected default variable names under the same rule.
## Environment False Signals
Before attributing a failure to the patch under review, exclude environment and source-selection problems with a control run.
- Confirm the commit and worktree under test. When editable installs, shared environments, `PYTHONPATH`, or generated artifacts can select stale code, verify the imported package path and rebuild before probing.
- Run base and head controls with the same interpreter, dependencies, environment variables, and command shape.
- Treat proxy initialization, sandbox denials, unavailable containers, expired snapshots, authentication, quotas, rate limits, service outages, and stale caches as environment conditions until a controlled rerun ties them to the patch.
- Never print proxy URLs or credentials. Change only the minimum in-scope environment or disposable state needed for the control run, and record which variable names or constraints changed.
In the final report, distinguish code failures, unsupported configurations, environment blockers, and inconclusive probes. Do not combine them into one failed-test count.
## Responses API Probe Patterns
For Responses API work, start from the uncertainty instead of from the full feature surface.
+4
View File
@@ -0,0 +1,4 @@
#:schema https://developers.openai.com/codex/config-schema.json
[features]
codex_hooks = true
+15
View File
@@ -0,0 +1,15 @@
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "uv run python \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_repo_tidy.py\"",
"timeout": 20
}
]
}
]
}
}
+222
View File
@@ -0,0 +1,222 @@
#!/usr/bin/env python3
from __future__ import annotations
import hashlib
import json
import subprocess
import sys
import tempfile
from dataclasses import asdict, dataclass
from pathlib import Path
MAX_RUFF_FIX_FILES = 20
PYTHON_SUFFIXES = {".py", ".pyi"}
@dataclass
class HookState:
last_tidy_fingerprint: str | None = None
def write_stop_block(reason: str, system_message: str) -> None:
sys.stdout.write(
json.dumps(
{
"decision": "block",
"reason": reason,
"systemMessage": system_message,
}
)
)
def run_command(cwd: str, *args: str) -> subprocess.CompletedProcess[str]:
try:
return subprocess.run(
args,
cwd=cwd,
capture_output=True,
check=False,
text=True,
)
except FileNotFoundError as exc:
return subprocess.CompletedProcess(args, returncode=127, stdout="", stderr=str(exc))
def run_git(cwd: str, *args: str) -> subprocess.CompletedProcess[str]:
return run_command(cwd, "git", *args)
def git_root(cwd: str) -> str:
result = run_git(cwd, "rev-parse", "--show-toplevel")
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git root lookup failed")
return result.stdout.strip()
def parse_status_paths(repo_root: str) -> list[str]:
unstaged = run_git(repo_root, "diff", "--name-only", "--diff-filter=ACMR")
untracked = run_git(repo_root, "ls-files", "--others", "--exclude-standard")
if unstaged.returncode != 0 or untracked.returncode != 0:
return []
paths = {
line.strip()
for result in (unstaged, untracked)
for line in result.stdout.splitlines()
if line.strip()
}
return sorted(paths)
def untracked_paths(repo_root: str, paths: list[str]) -> set[str]:
if not paths:
return set()
result = run_git(repo_root, "ls-files", "--others", "--exclude-standard", "--", *paths)
if result.returncode != 0:
return set()
return {line.strip() for line in result.stdout.splitlines() if line.strip()}
def fingerprint_for_paths(repo_root: str, paths: list[str]) -> str | None:
if not paths:
return None
repo_root_path = Path(repo_root)
untracked = untracked_paths(repo_root, paths)
tracked_paths = [file_path for file_path in paths if file_path not in untracked]
diff_parts: list[str] = []
if tracked_paths:
diff = run_git(repo_root, "diff", "--no-ext-diff", "--binary", "--", *tracked_paths)
if diff.returncode == 0:
diff_parts.append(diff.stdout)
for file_path in sorted(untracked):
try:
digest = hashlib.sha256((repo_root_path / file_path).read_bytes()).hexdigest()
except OSError:
continue
diff_parts.append(f"untracked:{file_path}:{digest}")
if not diff_parts:
return None
return hashlib.sha256("\n".join(diff_parts).encode("utf-8")).hexdigest()
def state_dir() -> Path:
return Path(tempfile.gettempdir()) / "openai-agents-python-codex-hooks"
def state_path(session_id: str, repo_root: str) -> Path:
root_hash = hashlib.sha256(repo_root.encode("utf-8")).hexdigest()[:12]
safe_session_id = "".join(
ch if ch.isascii() and (ch.isalnum() or ch in "._-") else "_" for ch in session_id
)
return state_dir() / f"{safe_session_id}-{root_hash}.json"
def load_state(session_id: str, repo_root: str) -> HookState:
file_path = state_path(session_id, repo_root)
if not file_path.exists():
return HookState()
try:
payload = json.loads(file_path.read_text())
except (OSError, json.JSONDecodeError):
return HookState()
return HookState(last_tidy_fingerprint=payload.get("last_tidy_fingerprint"))
def save_state(session_id: str, repo_root: str, state: HookState) -> None:
file_path = state_path(session_id, repo_root)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(json.dumps(asdict(state), indent=2))
def lint_fix_paths(repo_root: str) -> list[str]:
return [
file_path
for file_path in parse_status_paths(repo_root)
if Path(file_path).suffix in PYTHON_SUFFIXES
]
def main() -> None:
try:
payload = json.loads(sys.stdin.read() or "null")
except json.JSONDecodeError:
return
if not isinstance(payload, dict):
return
session_id = payload.get("session_id")
cwd = payload.get("cwd")
if not isinstance(session_id, str) or not isinstance(cwd, str):
return
if payload.get("stop_hook_active"):
return
repo_root = git_root(cwd)
current_paths = lint_fix_paths(repo_root)
if not current_paths or len(current_paths) > MAX_RUFF_FIX_FILES:
return
state = load_state(session_id, repo_root)
current_fingerprint = fingerprint_for_paths(repo_root, current_paths)
if current_fingerprint is None or state.last_tidy_fingerprint == current_fingerprint:
return
format_result = run_command(repo_root, "uv", "run", "ruff", "format", "--", *current_paths)
check_result: subprocess.CompletedProcess[str] | None = None
if format_result.returncode == 0:
check_result = run_command(
repo_root,
"uv",
"run",
"ruff",
"check",
"--fix",
"--",
*current_paths,
)
if format_result.returncode != 0:
write_stop_block(
"`uv run ruff format -- ...` failed for the touched Python files. "
"Review the formatting step before wrapping up.",
"Repo hook: targeted Ruff format failed.",
)
return
if check_result and check_result.returncode != 0:
write_stop_block(
"`uv run ruff check --fix -- ...` failed for the touched Python files. "
"Review the lint output before wrapping up.",
"Repo hook: targeted Ruff lint fix failed.",
)
return
updated_paths = lint_fix_paths(repo_root)
updated_fingerprint = fingerprint_for_paths(repo_root, updated_paths)
state.last_tidy_fingerprint = updated_fingerprint
save_state(session_id, repo_root, state)
if updated_fingerprint != current_fingerprint:
write_stop_block(
"I ran targeted tidy steps on the touched Python files "
"(`ruff format` and `ruff check --fix`). Review the updated diff, "
"then continue or wrap up.",
"Repo hook: ran targeted Ruff tidy on touched files.",
)
if __name__ == "__main__":
main()
+1 -1
View File
@@ -17,7 +17,7 @@ A clear and concise description of what the bug is.
### Debug information
- Agents SDK version: (e.g. `v0.0.3`)
- Python version (e.g. Python 3.10)
- Python version (e.g. Python 3.14)
### Repro steps
+1 -1
View File
@@ -17,7 +17,7 @@ A clear and concise description of what the question or bug is.
### Debug information
- Agents SDK version: (e.g. `v0.0.3`)
- Python version (e.g. Python 3.10)
- Python version (e.g. Python 3.14)
### Repro steps
Ideally provide a minimal python script that can be run to reproduce the issue.
@@ -5,6 +5,7 @@
### Test plan
<!-- Please explain how this was tested -->
<!-- If verification could not complete because of local environment setup, include the failing command, the missing dependency, and why it is unrelated to this PR. Leave the pass checkbox below unchecked until all verification steps pass. -->
### Issue number
@@ -12,7 +13,7 @@
### Checks
- [ ] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [ ] I've run `make lint` and `make format`
- [ ] I've made sure tests pass
- [ ] I've added new tests, if relevant
- [ ] I've run `.agents/skills/code-change-verification/scripts/run.sh`
- [ ] I've confirmed all verification steps pass
- [ ] If using Codex, I've run `/review` before submitting this PR
-71
View File
@@ -1,71 +0,0 @@
# PR auto-labeling
You are Codex running in CI to propose labels for a pull request in the openai-agents-python repository.
Inputs:
- PR context: .tmp/pr-labels/pr-context.json
- PR diff: .tmp/pr-labels/changes.diff
- Changed files: .tmp/pr-labels/changed-files.txt
Task:
- Inspect the PR context, diff, and changed files.
- Output JSON with a single top-level key: "labels" (array of strings).
- Only use labels from the allowed list.
- Prefer false negatives over false positives. If you are unsure, leave the label out.
- Return the smallest accurate set of labels for the PR's primary intent and primary surface area.
Allowed labels:
- documentation
- project
- bug
- enhancement
- dependencies
- feature:chat-completions
- feature:core
- feature:lite-llm
- feature:mcp
- feature:realtime
- feature:sessions
- feature:tracing
- feature:voice
Important guidance:
- `documentation`, `project`, and `dependencies` are also derived deterministically elsewhere in the workflow. You may include them when the evidence is explicit, but do not stretch to infer them from weak signals.
- Use direct evidence from changed implementation files and the dominant intent of the diff. Do not add labels based only on tests, examples, comments, docstrings, imports, type plumbing, or shared helpers.
- Cross-cutting features often touch many adapters and support layers. Only add a `feature:*` label when that area is itself a primary user-facing surface of the PR, not when it receives incidental compatibility or parity updates.
- Mentions of a feature area in helper names, comments, tests, or trace metadata are not enough by themselves.
- Prefer the most general accurate feature label over a larger set of narrower labels. For broad runtime work, this usually means `feature:core`.
- A secondary `feature:*` label needs two things: a non-test implementation/docs change in that area, and evidence that the area is a user-facing outcome of the PR rather than support work for another feature.
Label rules:
- documentation: Documentation changes (docs/), or src/ changes that only modify comments/docstrings without behavior changes. If only comments/docstrings change in src/, do not add bug/enhancement.
- project: Any change to pyproject.toml.
- dependencies: Dependencies are added/removed/updated (pyproject.toml dependency sections or uv.lock changes).
- bug: The PR's primary intent is to correct existing incorrect behavior. Use only with strong evidence such as the title/body/tests clearly describing a fix, regression, crash, incorrect output, or restore/preserve behavior. Do not add `bug` for incidental hardening that accompanies a new feature.
- enhancement: The PR's primary intent is to add or expand functionality. Prefer `enhancement` for feature work even if the diff also contains some fixes or guardrails needed to support that feature.
- bug vs enhancement: Prefer exactly one of these. Include both only when the PR clearly contains two separate substantial changes and both are first-order outcomes.
- feature:chat-completions: Chat Completions support or conversion is a primary deliverable of the PR. Do not add it for a small compatibility guard or parity update in `chatcmpl_converter.py`.
- feature:core: Core agent loop, tool calls, run pipeline, or other central runtime behavior is a primary surface of the PR. For cross-cutting runtime changes, this is usually the single best feature label.
- feature:lite-llm: LiteLLM adapter/provider behavior is a primary deliverable of the PR.
- feature:mcp: MCP-specific behavior or APIs are a primary deliverable of the PR. Do not add it for incidental hosted/deferred tool plumbing touched by broader runtime work.
- feature:realtime: Realtime-specific behavior, API shape, or session semantics are a primary deliverable of the PR. Do not add it for small parity updates in realtime adapters.
- feature:sessions: Session or memory behavior is a primary deliverable of the PR. Do not add it for persistence updates that merely support a broader feature.
- feature:tracing: Tracing is a primary deliverable of the PR. Do not add it for trace naming or metadata changes that accompany another feature.
- feature:voice: Voice pipeline behavior is a primary deliverable of the PR.
Decision process:
1. Determine the PR's primary intent in one sentence from the PR title/body and dominant runtime diff.
2. Start with zero labels.
3. Add `bug` or `enhancement` conservatively.
4. Add only the minimum `feature:*` labels needed to describe the primary surface area.
5. Treat extra `feature:*` labels as guilty until proven necessary. Keep them only when the PR would feel mislabeled without them.
6. Re-check every label. Drop any label that is supported only by secondary edits, parity work, or touched files outside the PR's main focus.
Examples:
- If a new cross-cutting runtime feature touches Chat Completions, Realtime, Sessions, MCP, and tracing support code for parity, prefer `["enhancement","feature:core"]` over labeling every touched area.
- If a PR mainly adds a Responses/core capability and touches realtime or sessions files only to keep shared serialization, replay, or adapters in sync, do not add `feature:realtime` or `feature:sessions`.
- If a PR mainly fixes realtime transport behavior and also updates tests/docs, prefer `["bug","feature:realtime"]`.
Output:
- JSON only (no code fences, no extra text).
- Example: {"labels":["enhancement","feature:core"]}
-23
View File
@@ -1,23 +0,0 @@
# Release readiness review
You are Codex running in CI. Produce a release readiness report for this repository.
Steps:
1. Determine the latest release tag (use local tags only):
- `git tag -l 'v*' --sort=-v:refname | head -n1`
2. Set TARGET to the current commit SHA: `git rev-parse HEAD`.
3. Collect diff context for BASE_TAG...TARGET:
- `git diff --stat BASE_TAG...TARGET`
- `git diff --dirstat=files,0 BASE_TAG...TARGET`
- `git diff --name-status BASE_TAG...TARGET`
- `git log --oneline --reverse BASE_TAG..TARGET`
4. Review `.agents/skills/final-release-review/references/review-checklist.md` and analyze the diff.
Output:
- Write the report in the exact format used by `$final-release-review` (see `.agents/skills/final-release-review/SKILL.md`).
- Use the compare URL: `https://github.com/${GITHUB_REPOSITORY}/compare/BASE_TAG...TARGET`.
- Include clear ship/block call and risk levels.
- If no risks are found, include "No material risks identified".
Constraints:
- Output only the report (no code fences, no extra commentary).
-28
View File
@@ -1,28 +0,0 @@
{
"type": "object",
"additionalProperties": false,
"required": ["labels"],
"properties": {
"labels": {
"type": "array",
"items": {
"type": "string",
"enum": [
"documentation",
"project",
"bug",
"enhancement",
"dependencies",
"feature:chat-completions",
"feature:core",
"feature:lite-llm",
"feature:mcp",
"feature:realtime",
"feature:sessions",
"feature:tracing",
"feature:voice"
]
}
}
}
}
-441
View File
@@ -1,441 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
import os
import pathlib
import subprocess
import sys
from collections.abc import Sequence
from dataclasses import dataclass
from typing import Any, Final
ALLOWED_LABELS: Final[set[str]] = {
"documentation",
"project",
"bug",
"enhancement",
"dependencies",
"feature:chat-completions",
"feature:core",
"feature:lite-llm",
"feature:mcp",
"feature:realtime",
"feature:sessions",
"feature:tracing",
"feature:voice",
}
DETERMINISTIC_LABELS: Final[set[str]] = {
"documentation",
"project",
"dependencies",
}
MODEL_ONLY_LABELS: Final[set[str]] = {
"bug",
"enhancement",
}
FEATURE_LABELS: Final[set[str]] = ALLOWED_LABELS - DETERMINISTIC_LABELS - MODEL_ONLY_LABELS
SOURCE_FEATURE_PREFIXES: Final[dict[str, tuple[str, ...]]] = {
"feature:realtime": ("src/agents/realtime/",),
"feature:voice": ("src/agents/voice/",),
"feature:mcp": ("src/agents/mcp/",),
"feature:tracing": ("src/agents/tracing/",),
"feature:sessions": ("src/agents/memory/", "src/agents/extensions/memory/"),
}
CORE_EXCLUDED_PREFIXES: Final[tuple[str, ...]] = (
"src/agents/realtime/",
"src/agents/voice/",
"src/agents/mcp/",
"src/agents/tracing/",
"src/agents/memory/",
"src/agents/extensions/",
"src/agents/models/",
)
PR_CONTEXT_DEFAULT_PATH = ".tmp/pr-labels/pr-context.json"
@dataclass(frozen=True)
class PRContext:
title: str = ""
body: str = ""
def read_file_at(commit: str | None, path: str) -> str | None:
if not commit:
return None
try:
return subprocess.check_output(["git", "show", f"{commit}:{path}"], text=True)
except subprocess.CalledProcessError:
return None
def dependency_lines_for_pyproject(text: str) -> set[int]:
dependency_lines: set[int] = set()
current_section: str | None = None
in_project_dependencies = False
for line_number, raw_line in enumerate(text.splitlines(), start=1):
stripped = raw_line.strip()
if stripped.startswith("[") and stripped.endswith("]"):
if stripped.startswith("[[") and stripped.endswith("]]"):
current_section = stripped[2:-2].strip()
else:
current_section = stripped[1:-1].strip()
in_project_dependencies = False
if current_section in ("project.optional-dependencies", "dependency-groups"):
dependency_lines.add(line_number)
continue
if current_section in ("project.optional-dependencies", "dependency-groups"):
dependency_lines.add(line_number)
continue
if current_section != "project":
continue
if in_project_dependencies:
dependency_lines.add(line_number)
if "]" in stripped:
in_project_dependencies = False
continue
if stripped.startswith("dependencies") and "=" in stripped:
dependency_lines.add(line_number)
if "[" in stripped and "]" not in stripped:
in_project_dependencies = True
return dependency_lines
def pyproject_dependency_changed(
diff_text: str,
*,
base_sha: str | None,
head_sha: str | None,
) -> bool:
import re
base_text = read_file_at(base_sha, "pyproject.toml")
head_text = read_file_at(head_sha, "pyproject.toml")
if base_text is None and head_text is None:
return False
base_dependency_lines = dependency_lines_for_pyproject(base_text) if base_text else set()
head_dependency_lines = dependency_lines_for_pyproject(head_text) if head_text else set()
in_pyproject = False
base_line: int | None = None
head_line: int | None = None
hunk_re = re.compile(r"@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@")
for line in diff_text.splitlines():
if line.startswith("+++ b/"):
current_file = line[len("+++ b/") :].strip()
in_pyproject = current_file == "pyproject.toml"
base_line = None
head_line = None
continue
if not in_pyproject:
continue
if line.startswith("@@ "):
match = hunk_re.match(line)
if not match:
continue
base_line = int(match.group(1))
head_line = int(match.group(2))
continue
if base_line is None or head_line is None:
continue
if line.startswith(" "):
base_line += 1
head_line += 1
continue
if line.startswith("-"):
if base_line in base_dependency_lines:
return True
base_line += 1
continue
if line.startswith("+"):
if head_line in head_dependency_lines:
return True
head_line += 1
continue
return False
def infer_specific_feature_labels(changed_files: Sequence[str]) -> set[str]:
source_files = [path for path in changed_files if path.startswith("src/")]
labels: set[str] = set()
for label, prefixes in SOURCE_FEATURE_PREFIXES.items():
if any(path.startswith(prefix) for path in source_files for prefix in prefixes):
labels.add(label)
if any(
path.startswith(("src/agents/models/", "src/agents/extensions/models/"))
and ("chatcmpl" in path or "chatcompletions" in path)
for path in source_files
):
labels.add("feature:chat-completions")
if any(
path.startswith(("src/agents/models/", "src/agents/extensions/models/"))
and "litellm" in path
for path in source_files
):
labels.add("feature:lite-llm")
return labels
def infer_feature_labels(changed_files: Sequence[str]) -> set[str]:
source_files = [path for path in changed_files if path.startswith("src/")]
specific_labels = infer_specific_feature_labels(source_files)
core_touched = any(
path.startswith("src/agents/") and not path.startswith(CORE_EXCLUDED_PREFIXES)
for path in source_files
)
if core_touched and len(specific_labels) != 1:
return {"feature:core"}
return specific_labels
def infer_fallback_labels(changed_files: Sequence[str]) -> set[str]:
return infer_feature_labels(changed_files)
def load_json(path: pathlib.Path) -> Any:
return json.loads(path.read_text())
def load_pr_context(path: pathlib.Path) -> PRContext:
if not path.exists():
return PRContext()
try:
payload = load_json(path)
except json.JSONDecodeError:
return PRContext()
if not isinstance(payload, dict):
return PRContext()
title = payload.get("title", "")
body = payload.get("body", "")
if not isinstance(title, str):
title = ""
if not isinstance(body, str):
body = ""
return PRContext(title=title, body=body)
def load_codex_labels(path: pathlib.Path) -> tuple[list[str], bool]:
if not path.exists():
return [], False
raw = path.read_text().strip()
if not raw:
return [], False
try:
payload = load_json(path)
except json.JSONDecodeError:
return [], False
if not isinstance(payload, dict):
return [], False
labels = payload.get("labels")
if not isinstance(labels, list):
return [], False
if not all(isinstance(label, str) for label in labels):
return [], False
return list(labels), True
def fetch_existing_labels(pr_number: str) -> set[str]:
result = subprocess.check_output(
["gh", "pr", "view", pr_number, "--json", "labels", "--jq", ".labels[].name"],
text=True,
).strip()
return {label for label in result.splitlines() if label}
def infer_title_intent_labels(pr_context: PRContext) -> set[str]:
normalized_title = pr_context.title.strip().lower()
bug_prefixes = ("fix:", "fix(", "bug:", "bugfix:", "hotfix:", "regression:")
enhancement_prefixes = ("feat:", "feat(", "feature:", "enhancement:")
if normalized_title.startswith(bug_prefixes):
return {"bug"}
if normalized_title.startswith(enhancement_prefixes):
return {"enhancement"}
return set()
def compute_desired_labels(
*,
pr_context: PRContext,
changed_files: Sequence[str],
diff_text: str,
codex_ran: bool,
codex_output_valid: bool,
codex_labels: Sequence[str],
base_sha: str | None,
head_sha: str | None,
) -> set[str]:
desired: set[str] = set()
codex_label_set = {label for label in codex_labels if label in ALLOWED_LABELS}
codex_feature_labels = codex_label_set & FEATURE_LABELS
codex_model_only_labels = codex_label_set & MODEL_ONLY_LABELS
fallback_feature_labels = infer_fallback_labels(changed_files)
title_intent_labels = infer_title_intent_labels(pr_context)
if "pyproject.toml" in changed_files:
desired.add("project")
if any(path.startswith("docs/") for path in changed_files):
desired.add("documentation")
dependencies_allowed = "uv.lock" in changed_files
if "pyproject.toml" in changed_files and pyproject_dependency_changed(
diff_text, base_sha=base_sha, head_sha=head_sha
):
dependencies_allowed = True
if dependencies_allowed:
desired.add("dependencies")
if codex_ran and codex_output_valid and codex_feature_labels:
desired.update(codex_feature_labels)
else:
desired.update(fallback_feature_labels)
if title_intent_labels:
desired.update(title_intent_labels)
elif codex_ran and codex_output_valid:
desired.update(codex_model_only_labels)
return desired
def compute_managed_labels(
*,
pr_context: PRContext,
codex_ran: bool,
codex_output_valid: bool,
codex_labels: Sequence[str],
) -> set[str]:
managed = DETERMINISTIC_LABELS | FEATURE_LABELS
title_intent_labels = infer_title_intent_labels(pr_context)
codex_label_set = {label for label in codex_labels if label in MODEL_ONLY_LABELS}
if title_intent_labels or (codex_ran and codex_output_valid and codex_label_set):
managed |= MODEL_ONLY_LABELS
return managed
def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--pr-number", default=os.environ.get("PR_NUMBER", ""))
parser.add_argument("--base-sha", default=os.environ.get("PR_BASE_SHA", ""))
parser.add_argument("--head-sha", default=os.environ.get("PR_HEAD_SHA", ""))
parser.add_argument(
"--codex-output-path",
default=os.environ.get("CODEX_OUTPUT_PATH", ".tmp/codex/outputs/pr-labels.json"),
)
parser.add_argument("--codex-conclusion", default=os.environ.get("CODEX_CONCLUSION", ""))
parser.add_argument(
"--pr-context-path",
default=os.environ.get("PR_CONTEXT_PATH", PR_CONTEXT_DEFAULT_PATH),
)
parser.add_argument(
"--changed-files-path",
default=os.environ.get("CHANGED_FILES_PATH", ".tmp/pr-labels/changed-files.txt"),
)
parser.add_argument(
"--changes-diff-path",
default=os.environ.get("CHANGES_DIFF_PATH", ".tmp/pr-labels/changes.diff"),
)
return parser.parse_args(argv)
def main(argv: Sequence[str] | None = None) -> int:
args = parse_args(argv)
if not args.pr_number:
raise SystemExit("Missing PR number.")
changed_files_path = pathlib.Path(args.changed_files_path)
changes_diff_path = pathlib.Path(args.changes_diff_path)
codex_output_path = pathlib.Path(args.codex_output_path)
pr_context_path = pathlib.Path(args.pr_context_path)
codex_conclusion = args.codex_conclusion.strip().lower()
codex_ran = bool(codex_conclusion) and codex_conclusion != "skipped"
pr_context = load_pr_context(pr_context_path)
changed_files = []
if changed_files_path.exists():
changed_files = [
line.strip() for line in changed_files_path.read_text().splitlines() if line.strip()
]
diff_text = changes_diff_path.read_text() if changes_diff_path.exists() else ""
codex_labels, codex_output_valid = load_codex_labels(codex_output_path)
if codex_ran and not codex_output_valid:
print(
"Codex output missing or invalid; using fallback feature labels and preserving "
"model-only labels."
)
desired = compute_desired_labels(
pr_context=pr_context,
changed_files=changed_files,
diff_text=diff_text,
codex_ran=codex_ran,
codex_output_valid=codex_output_valid,
codex_labels=codex_labels,
base_sha=args.base_sha or None,
head_sha=args.head_sha or None,
)
existing = fetch_existing_labels(args.pr_number)
managed_labels = compute_managed_labels(
pr_context=pr_context,
codex_ran=codex_ran,
codex_output_valid=codex_output_valid,
codex_labels=codex_labels,
)
to_add = sorted(desired - existing)
to_remove = sorted((existing & managed_labels) - desired)
if not to_add and not to_remove:
print("Labels already up to date.")
return 0
cmd = ["gh", "pr", "edit", args.pr_number]
if to_add:
cmd += ["--add-label", ",".join(to_add)]
if to_remove:
cmd += ["--remove-label", ",".join(to_remove)]
subprocess.check_call(cmd)
return 0
if __name__ == "__main__":
sys.exit(main())
+3 -2
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Determine docs-only push
id: docs-only
run: |
@@ -36,8 +36,9 @@ jobs:
fi
- name: Setup uv
if: steps.docs-only.outputs.skip != 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Install dependencies
if: steps.docs-only.outputs.skip != 'true'
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
issues: write
pull-requests: write
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899
with:
days-before-issue-stale: 7
days-before-issue-close: 3
-204
View File
@@ -1,204 +0,0 @@
name: Auto label PRs
on:
pull_request_target:
types:
- opened
- reopened
- synchronize
- ready_for_review
workflow_dispatch:
inputs:
pr_number:
description: "PR number to label."
required: true
type: number
permissions:
contents: read
issues: write
pull-requests: write
jobs:
label:
runs-on: ubuntu-latest
steps:
- name: Ensure main workflow
if: ${{ github.event_name == 'workflow_dispatch' && github.ref != 'refs/heads/main' }}
run: |
echo "This workflow must be dispatched from main."
exit 1
- name: Resolve PR context
id: pr
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
env:
MANUAL_PR_NUMBER: ${{ inputs.pr_number || '' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const isManual = context.eventName === 'workflow_dispatch';
let pr;
if (isManual) {
const prNumber = Number(process.env.MANUAL_PR_NUMBER);
if (!prNumber) {
core.setFailed('workflow_dispatch requires pr_number input.');
return;
}
const { data } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
pr = data;
} else {
pr = context.payload.pull_request;
}
if (!pr) {
core.setFailed('Missing pull request context.');
return;
}
const headRepo = pr.head.repo.full_name;
const repoFullName = `${context.repo.owner}/${context.repo.repo}`;
core.setOutput('pr_number', pr.number);
core.setOutput('base_sha', pr.base.sha);
core.setOutput('head_sha', pr.head.sha);
core.setOutput('head_repo', headRepo);
core.setOutput('is_fork', headRepo !== repoFullName);
core.setOutput('title', pr.title || '');
core.setOutput('body', pr.body || '');
- name: Checkout base
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
ref: ${{ steps.pr.outputs.base_sha }}
- name: Fetch PR head
env:
PR_HEAD_REPO: ${{ steps.pr.outputs.head_repo }}
PR_HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
run: |
set -euo pipefail
git fetch --no-tags --prune --recurse-submodules=no \
"https://github.com/${PR_HEAD_REPO}.git" \
"${PR_HEAD_SHA}"
- name: Collect PR diff
id: diff
env:
PR_BASE_SHA: ${{ steps.pr.outputs.base_sha }}
PR_HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
PR_TITLE: ${{ steps.pr.outputs.title }}
PR_BODY: ${{ steps.pr.outputs.body }}
run: |
set -euo pipefail
mkdir -p .tmp/pr-labels
diff_base_sha="$(git merge-base "$PR_BASE_SHA" "$PR_HEAD_SHA")"
echo "diff_base_sha=${diff_base_sha}" >> "$GITHUB_OUTPUT"
git diff --name-only "$diff_base_sha" "$PR_HEAD_SHA" > .tmp/pr-labels/changed-files.txt
git diff "$diff_base_sha" "$PR_HEAD_SHA" > .tmp/pr-labels/changes.diff
python - <<'PY'
import json
import os
import pathlib
pathlib.Path(".tmp/pr-labels/pr-context.json").write_text(
json.dumps(
{
"title": os.environ.get("PR_TITLE", ""),
"body": os.environ.get("PR_BODY", ""),
},
ensure_ascii=False,
indent=2,
)
+ "\n"
)
PY
- name: Prepare Codex output
id: codex-output
run: |
set -euo pipefail
output_dir=".tmp/codex/outputs"
output_file="${output_dir}/pr-labels.json"
mkdir -p "$output_dir"
echo "output_file=${output_file}" >> "$GITHUB_OUTPUT"
- name: Run Codex labeling
id: run_codex
if: ${{ (github.event_name == 'workflow_dispatch' || steps.pr.outputs.is_fork != 'true') && github.actor != 'dependabot[bot]' }}
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/pr-labels.md
output-file: ${{ steps.codex-output.outputs.output_file }}
output-schema-file: .github/codex/schemas/pr-labels.json
# Keep the legacy Linux sandbox path until the default bubblewrap path
# works reliably on GitHub-hosted Ubuntu runners.
codex-args: '["--enable","use_legacy_landlock"]'
safety-strategy: drop-sudo
sandbox: read-only
- name: Apply labels
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr.outputs.pr_number }}
PR_BASE_SHA: ${{ steps.diff.outputs.diff_base_sha }}
PR_HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
CODEX_OUTPUT_PATH: ${{ steps.codex-output.outputs.output_file }}
CODEX_CONCLUSION: ${{ steps.run_codex.conclusion }}
run: |
python .github/scripts/pr_labels.py
- name: Comment on manual run failure
if: ${{ github.event_name == 'workflow_dispatch' && always() }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
env:
PR_NUMBER: ${{ steps.pr.outputs.pr_number }}
JOB_STATUS: ${{ job.status }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
CODEX_CONCLUSION: ${{ steps.run_codex.conclusion }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const marker = '<!-- pr-labels-manual-run -->';
const jobStatus = process.env.JOB_STATUS;
if (jobStatus === 'success') {
return;
}
const prNumber = Number(process.env.PR_NUMBER);
if (!prNumber) {
core.setFailed('Missing PR number for manual run comment.');
return;
}
const body = [
marker,
'Manual PR labeling failed.',
`Job status: ${jobStatus}.`,
`Run: ${process.env.RUN_URL}.`,
`Codex labeling: ${process.env.CODEX_CONCLUSION}.`,
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
per_page: 100,
});
const existing = comments.find(
(comment) =>
comment.user?.login === 'github-actions[bot]' &&
comment.body?.includes(marker),
);
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
core.info(`Updated existing comment ${existing.id}`);
return;
}
const { data: created } = await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
core.info(`Created comment ${created.id}`);
+4 -3
View File
@@ -21,14 +21,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Setup uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Install dependencies
run: make sync
- name: Build package
run: uv build
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b
-109
View File
@@ -1,109 +0,0 @@
name: Update release PR on main updates
on:
push:
branches:
- main
concurrency:
group: release-pr-update
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
jobs:
update-release-pr:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch origin --tags --prune
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Find release PR
id: find
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
base_branch="main"
prs_json="$(gh pr list \
--base "$base_branch" \
--state open \
--search "head:release/v" \
--limit 200 \
--json number,headRefName,isCrossRepository,headRepositoryOwner)"
count="$(echo "$prs_json" | jq '[.[] | select(.isCrossRepository == false) | select(.headRefName|startswith("release/v"))] | length')"
if [ "$count" -eq 0 ]; then
echo "found=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "$count" -gt 1 ]; then
echo "Multiple release PRs found; expected a single release PR." >&2
exit 1
fi
number="$(echo "$prs_json" | jq -r '.[] | select(.isCrossRepository == false) | select(.headRefName|startswith("release/v")) | .number')"
branch="$(echo "$prs_json" | jq -r '.[] | select(.isCrossRepository == false) | select(.headRefName|startswith("release/v")) | .headRefName')"
echo "found=true" >> "$GITHUB_OUTPUT"
echo "number=$number" >> "$GITHUB_OUTPUT"
echo "branch=$branch" >> "$GITHUB_OUTPUT"
- name: Rebase release branch
if: steps.find.outputs.found == 'true'
env:
RELEASE_BRANCH: ${{ steps.find.outputs.branch }}
run: |
set -euo pipefail
git fetch origin main "$RELEASE_BRANCH"
git checkout -B "$RELEASE_BRANCH" "origin/$RELEASE_BRANCH"
git rebase origin/main
- name: Prepare Codex output
if: steps.find.outputs.found == 'true'
id: codex-output
run: |
set -euo pipefail
output_dir=".tmp/codex/outputs"
output_file="${output_dir}/release-review.md"
mkdir -p "$output_dir"
echo "output_file=${output_file}" >> "$GITHUB_OUTPUT"
- name: Run Codex release review
if: steps.find.outputs.found == 'true'
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/release-review.md
output-file: ${{ steps.codex-output.outputs.output_file }}
# Keep the legacy Linux sandbox path until the default bubblewrap path
# works reliably on GitHub-hosted Ubuntu runners.
codex-args: '["--enable","use_legacy_landlock"]'
safety-strategy: drop-sudo
sandbox: read-only
- name: Update PR body and push
if: steps.find.outputs.found == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.find.outputs.number }}
RELEASE_BRANCH: ${{ steps.find.outputs.branch }}
RELEASE_REVIEW_PATH: ${{ steps.codex-output.outputs.output_file }}
run: |
set -euo pipefail
git push --force-with-lease origin "$RELEASE_BRANCH"
gh pr edit "$PR_NUMBER" --body-file "$RELEASE_REVIEW_PATH"
version="${RELEASE_BRANCH#release/v}"
milestone_name="$(python .github/scripts/select-release-milestone.py --version "$version")"
if [ -n "$milestone_name" ]; then
if ! gh pr edit "$PR_NUMBER" --add-label "project" --milestone "$milestone_name"; then
echo "PR label/milestone update failed; continuing without changes." >&2
fi
else
if ! gh pr edit "$PR_NUMBER" --add-label "project"; then
echo "PR label update failed; continuing without changes." >&2
fi
fi
+5 -29
View File
@@ -16,13 +16,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
fetch-depth: 0
ref: main
- name: Setup uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Fetch tags
run: git fetch origin --tags --prune
@@ -92,36 +93,11 @@ jobs:
fi
git commit -m "Bump version to ${RELEASE_VERSION}"
git push --set-upstream origin "$branch"
- name: Prepare Codex output
id: codex-output
run: |
set -euo pipefail
output_dir=".tmp/codex/outputs"
output_file="${output_dir}/release-review.md"
mkdir -p "$output_dir"
echo "output_file=${output_file}" >> "$GITHUB_OUTPUT"
- name: Run Codex release review
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/release-review.md
output-file: ${{ steps.codex-output.outputs.output_file }}
# Keep the legacy Linux sandbox path until the default bubblewrap path
# works reliably on GitHub-hosted Ubuntu runners.
codex-args: '["--enable","use_legacy_landlock"]'
safety-strategy: drop-sudo
sandbox: read-only
- name: Build PR body
env:
RELEASE_REVIEW_PATH: ${{ steps.codex-output.outputs.output_file }}
RELEASE_VERSION: ${{ inputs.version }}
run: |
python - <<'PY'
import os
import pathlib
report = pathlib.Path(os.environ["RELEASE_REVIEW_PATH"]).read_text()
pathlib.Path("pr-body.md").write_text(report)
PY
printf 'Release PR for %s.\n\nThe release readiness report will be prepared manually.\n' "$RELEASE_VERSION" > pr-body.md
- name: Create or update PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -2
View File
@@ -14,6 +14,7 @@ jobs:
tag-release:
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.head.repo.full_name == github.repository &&
startsWith(github.event.pull_request.head.ref, 'release/v')
runs-on: ubuntu-latest
steps:
@@ -26,12 +27,12 @@ jobs:
exit 1
fi
- name: Checkout merge commit
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.merge_commit_sha }}
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.11"
- name: Configure git
+40 -8
View File
@@ -18,14 +18,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Detect code changes
id: changes
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Install dependencies
if: steps.changes.outputs.run == 'true'
@@ -44,14 +45,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Detect code changes
id: changes
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Install dependencies
if: steps.changes.outputs.run == 'true'
@@ -78,14 +80,15 @@ jobs:
OPENAI_API_KEY: fake-for-tests
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Detect code changes
id: changes
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
python-version: ${{ matrix.python-version }}
- name: Install dependencies
@@ -104,20 +107,49 @@ jobs:
if: steps.changes.outputs.run != 'true'
run: echo "Skipping tests for non-code changes."
tests-windows:
runs-on: windows-latest
env:
OPENAI_API_KEY: fake-for-tests
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Detect code changes
id: changes
shell: bash
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
python-version: "3.13"
- name: Install dependencies
if: steps.changes.outputs.run == 'true'
run: uv sync --all-extras --all-packages --group dev
- name: Run tests
if: steps.changes.outputs.run == 'true'
run: uv run pytest
- name: Skip tests
if: steps.changes.outputs.run != 'true'
run: echo "Skipping tests for non-code changes."
build-docs:
runs-on: ubuntu-latest
env:
OPENAI_API_KEY: fake-for-tests
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Detect docs changes
id: changes
run: ./.github/scripts/detect-changes.sh docs "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
- name: Install dependencies
if: steps.changes.outputs.run == 'true'
-88
View File
@@ -1,88 +0,0 @@
name: "Update Translated Docs"
# This GitHub Actions job automates the process of updating all translated document pages. Please note the following:
# 1. The translation results may vary each time; some differences in detail are expected.
# 2. When you add a new page to the left-hand menu, **make sure to manually update mkdocs.yml** to include the new item.
# 3. If you switch to a different LLM (for example, from o3 to a newer model), be sure to conduct thorough testing before making the switch.
# To add more languages, you will update the following:
# 1. Add '!docs/{lang}/**' to `on.push.paths` in this file
# 2. Update mkdocs.yml to have the new language
# 3. Update docs/scripts/translate_docs.py to have the new language
on:
push:
branches:
- main
paths:
- 'docs/**'
- mkdocs.yml
- '!docs/ja/**'
- '!docs/ko/**'
- '!docs/zh/**'
workflow_dispatch:
inputs:
translate_mode:
description: "Translation mode"
type: choice
options:
- only-changes
- full
default: only-changes
permissions:
contents: write
pull-requests: write
jobs:
update-docs:
if: "!contains(github.event.head_commit.message, 'Update all translated document pages')"
name: Build and Push Translated Docs
runs-on: ubuntu-latest
timeout-minutes: 30
env:
PROD_OPENAI_API_KEY: ${{ secrets.PROD_OPENAI_API_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
with:
enable-cache: true
- name: Install dependencies
run: make sync
- name: Build translated docs
run: |
mode="${{ inputs.translate_mode || 'only-changes' }}"
uv run docs/scripts/translate_docs.py --mode "$mode"
uv run mkdocs build
- name: Commit changes
id: commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/
if git diff --cached --quiet; then
echo "No changes to commit"
echo "committed=false" >> "$GITHUB_OUTPUT"
else
git commit -m "Update all translated document pages"
echo "committed=true" >> "$GITHUB_OUTPUT"
fi
- name: Create Pull Request
if: steps.commit.outputs.committed == 'true'
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
commit-message: "Update translated document pages"
title: "docs: update translated document pages"
body: |
Automated update of translated documentation.
Triggered by commit: [${{ github.event.head_commit.id }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.event.head_commit.id }}).
Message: `${{ github.event.head_commit.message }}`
branch: update-translated-docs-${{ github.run_id }}
delete-branch: true
+5
View File
@@ -143,6 +143,10 @@ cython_debug/
# Ruff stuff:
.ruff_cache/
# Example runtime state
examples/sandbox/extensions/daytona/usaspending_text2sql/.audit_log.jsonl
examples/sandbox/extensions/daytona/usaspending_text2sql/.session_state.json
# PyPI configuration file
.pypirc
.aider*
@@ -154,3 +158,4 @@ tmp/
# execplans
plans/
.vercel
+46 -23
View File
@@ -36,17 +36,25 @@ Before changing runtime code, exported APIs, external configuration, persisted s
#### `$pr-draft-summary`
When a task in this repo finishes with moderate-or-larger code changes, invoke `$pr-draft-summary` in the final handoff to generate the required PR summary block, branch suggestion, title, and draft description. Treat this as the default close-out step after runtime code, tests, examples, build/test configuration, or docs with behavior impact are changed.
Before every final response for a task that changed runtime code, tests, examples, build/test configuration, or docs with behavior impact, invoke `$pr-draft-summary` to generate the required PR summary block, branch suggestion, title, and draft description. Determine whether to invoke it from the changed files, not from a subjective assessment of change size.
Skip `$pr-draft-summary` only for trivial or conversation-only tasks, repo-meta/doc-only tasks without behavior impact, or when the user explicitly says not to include the PR draft block.
Producing the PR draft block is part of the local final handoff. It is required for eligible local-only or uncommitted changes and does not authorize creating a branch, committing, pushing, or opening a pull request.
### Git Worktree and Branch Safety
Work in the user's current checkout and on the current branch by default. If the Codex task is already running in a selected Git worktree, use that worktree without requesting additional permission. Do not create or switch to another Git worktree, and do not create or switch branches, unless the user explicitly asks for or approves that exact action in the current conversation. A request to implement, investigate, review, test, or verify changes does not by itself authorize changing the active worktree or branch.
If isolation or a different checkout is needed, explain why and ask the user before changing Git state. This requirement also applies when another rule or workflow recommends a linked worktree: stop and request approval instead of choosing or creating one automatically.
### ExecPlans
Call out compatibility risk early in your plan only when the change affects behavior shipped in the latest release tag or a released or explicitly supported durable external state boundary, and confirm the approach before implementing changes that could impact users.
Use an ExecPlan when work is multi-step, spans several files, involves new features or refactors, or is likely to take more than about an hour. Start with the template and rules in `PLANS.md`, keep milestones and living sections (Progress, Surprises & Discoveries, Decision Log, Outcomes & Retrospective) up to date as you execute, and rewrite the plan if scope shifts. Call out compatibility risk only when the plan changes behavior shipped in the latest release tag or a released or explicitly supported durable external state boundary. Do not treat branch-local interface churn or unreleased post-tag changes on `main` as breaking by default; prefer direct replacement over compatibility layers in those cases, and renumber or squash unreleased persisted schemas before release when the intermediate snapshots are intentionally unsupported. If you intentionally skip an ExecPlan for a complex task, note why in your response so reviewers understand the choice.
### Public API Positional Compatibility
### Public API Compatibility
Treat the parameter and dataclass field order of exported runtime APIs as a compatibility contract.
@@ -54,6 +62,17 @@ Treat the parameter and dataclass field order of exported runtime APIs as a comp
- When adding a new optional public field/parameter, append it to the end whenever possible and keep old fields in the same order.
- If reordering is unavoidable, add an explicit compatibility layer and regression tests that exercise the old positional call pattern.
- Prefer keyword arguments at call sites to reduce accidental breakage, but do not rely on this to justify breaking positional compatibility for public APIs.
- Treat intended import paths and `__all__` membership as compatibility contracts. When adding or moving a public symbol, update the owning module, intended top-level or subpackage re-exports, and an import regression test. Keep top-level imports free of optional-dependency failures and runtime side effects; use lazy exports when needed.
### Platform, Docs, and Security Review
- Documentation is published to the live site, so coordinate SDK behavior changes and docs carefully. If docs describe behavior that is not released yet, either delay the docs change until the SDK release is available or split it into a follow-up PR.
- Treat runnable docs snippets as API compatibility checks. Before adding OpenAI API, provider, Responses, Realtime, WebSocket, or SDK constructor examples, verify the shown arguments and call shape against the actual implementation.
- Do not let untrusted sandbox manifests opt themselves out of host filesystem or base-directory boundaries. Escape hatches for local source materialization must be controlled by trusted application code at the call site, not by serialized manifest data.
- When documenting sandbox or security grants, verify the actual implementation path enforces the grant or boundary. Do not claim a grant applies to `LocalDir`, `LocalFile`, archive extraction, or other materialization paths unless those paths actually consult it.
- When redacting OpenAI tool, MCP, model, or provider payloads, consider traceback display, exception chaining, `__context__`, logs, and telemetry. Suppressing display with `raise ... from None` is not enough if the original exception object still carries sensitive input data.
- For OpenAI platform or SDK-specific docs changes, prefer `$openai-knowledge` for authoritative platform behavior and inspect the local code path for SDK behavior. Do not rely on generic API assumptions when documenting Responses, Chat Completions, Realtime, tools, MCP, or provider adapters.
- For Realtime tracing changes, read [Realtime tracing architecture](.agents/references/realtime-tracing.md) before proposing SDK spans. Realtime API server traces and Agents SDK client traces are separate; `group_id` can correlate them but does not create a shared trace hierarchy.
## Project Structure Guide
@@ -72,25 +91,28 @@ The OpenAI Agents Python repository provides the Python Agents SDK, examples, an
- `Makefile`: Common developer commands.
- `pyproject.toml`, `uv.lock`: Python dependencies and tool configuration.
- `.github/PULL_REQUEST_TEMPLATE/pull_request_template.md`: Pull request template to use when opening PRs.
- `.agents/references/`: Durable SDK maintainer architecture references. Start with [the reference map](.agents/references/README.md) and open only the files relevant to the affected runtime boundary.
- `site/`: Built documentation output.
### Agents Core Runtime Guidelines
- For `Agent` fields, cloning, dynamic instructions, enabled tools or handoffs, output schemas, run context wrappers, usage aggregation, or public-versus-internal agent identity, read [Agent definition and run context](.agents/references/agent-definition-and-run-context.md).
- `src/agents/run.py` is the runtime entrypoint (`Runner`, `AgentRunner`). Keep it focused on orchestration and public flow control. Put new runtime logic under `src/agents/run_internal/` and import it into `run.py`.
- When `run.py` grows, refactor helpers into `run_internal/` modules (for example `run_loop.py`, `turn_resolution.py`, `tool_execution.py`, `session_persistence.py`) and leave only wiring and composition in `run.py`.
- Keep streaming and non-streaming paths behaviorally aligned. Changes to `run_internal/run_loop.py` (`run_single_turn`, `run_single_turn_streamed`, `get_new_response`, `start_streaming`) should be mirrored, and any new streaming item types must be reflected in `src/agents/stream_events.py`.
- Input guardrails run only on the first turn and only for the starting agent. Resuming an interruption from `RunState` must not increment the turn counter; only actual model calls advance turns.
- Server-managed conversation (`conversation_id`, `previous_response_id`, `auto_previous_response_id`) uses `OpenAIServerConversationTracker` in `run_internal/oai_conversation.py`. Only deltas should be sent. If `call_model_input_filter` is used, it must return `ModelInputData` with a list input and the tracker must be updated with the filtered input (`mark_input_as_sent`). Session persistence is disabled when server-managed conversation is active.
- Adding new tool/output/approval item types requires coordinated updates across:
- `src/agents/items.py` (RunItem types and conversions)
- `src/agents/run_internal/run_steps.py` (ProcessedResponse and tool run structs)
- `src/agents/run_internal/turn_resolution.py` (model output processing, run item extraction)
- `src/agents/run_internal/tool_execution.py` and `src/agents/run_internal/tool_planning.py`
- `src/agents/run_internal/items.py` (normalization, dedupe, approval filtering)
- `src/agents/stream_events.py` (stream event names)
- `src/agents/run_state.py` (RunState serialization/deserialization)
- `src/agents/run_internal/session_persistence.py` (session save/rewind)
- If the serialized RunState shape changes, update `CURRENT_SCHEMA_VERSION` in `src/agents/run_state.py` and the related serialization/deserialization logic. Keep released schema versions readable, and feel free to renumber or squash unreleased schema versions before release when those intermediate snapshots are intentionally unsupported.
- For turn accounting, guardrail ordering, handoffs, interruptions, cancellation, hooks, or streaming behavior, read [Runner lifecycle](.agents/references/runner-lifecycle.md). Keep streaming and non-streaming paths behaviorally aligned.
- For new model output, tool call, approval, or run item variants, read [Run item lifecycle](.agents/references/run-item-lifecycle.md) and update every applicable processing, event, replay, persistence, tracing, and serialization surface.
- For function-tool parameter schemas, `Annotated` or `Field` metadata, strict JSON schema conversion, or structured output schemas, read [Function and output schema](.agents/references/function-and-output-schema.md).
- For function-tool naming, namespacing, lookup, approvals, tracing, or call-ID changes, read [Tool identity and routing](.agents/references/tool-identity.md) and use the canonical helpers in `src/agents/_tool_identity.py` instead of adding local normalization rules.
- For function-tool planning, approval ordering, tool guardrails, concurrency, cancellation, timeouts, hooks, or failure conversion, read [Tool execution lifecycle](.agents/references/tool-execution-lifecycle.md).
- For local MCP connection ownership, `MCPServerManager`, request serialization, tool caching or filtering, transport retries, cancellation, or cleanup, read [Local MCP server lifecycle](.agents/references/local-mcp-server-lifecycle.md).
- For trace or span context, processors, export, flush, shutdown, sensitive data, or resumed trace state, read [Tracing lifecycle](.agents/references/tracing-lifecycle.md).
- For `RealtimeSession` lifecycle, background-task, handoff, listener, connection, or cleanup changes, read [Realtime session lifecycle](.agents/references/realtime-session-lifecycle.md) and verify both normal and failure-path resource ownership.
- For `VoicePipeline`, streamed audio input, STT session ownership, TTS task ordering, voice lifecycle events, PCM framing, or voice tracing changes, read [Voice pipeline lifecycle](.agents/references/voice-pipeline-lifecycle.md).
- For server-managed conversation (`conversation_id`, `previous_response_id`, `auto_previous_response_id`), read [Conversation state ownership](.agents/references/conversation-state-ownership.md) before changing continuation, filtering, retry, compaction, handoffs, or resume behavior.
- For client-managed session input, per-turn saves, retry rewind, backend atomicity, or compaction replacement, read [Session persistence](.agents/references/session-persistence.md).
- For model resolution, `ModelSettings`, provider adapters, Responses versus Chat Completions capabilities, request conversion, terminal events, transport reuse, or model retries, read [Model and provider boundaries](.agents/references/model-provider-boundaries.md).
- If the serialized `RunState` shape changes, read [RunState schema and resume boundary](.agents/references/runstate-schema.md) and follow its release-boundary, schema-version, backward-read, and regression-test rules.
- For sandbox session ownership, agent preparation, manifests, host-path materialization, snapshots, resume state, or cleanup, read [Sandbox runtime boundary](.agents/references/sandbox-runtime-boundary.md).
## Operation Guide
@@ -102,20 +124,21 @@ The OpenAI Agents Python repository provides the Python Agents SDK, examples, an
### Development Workflow
1. Sync with `main` and create a feature branch:
1. Stay in the user's current checkout and on the current branch unless the user explicitly asks for or approves a Git state change.
2. If the user explicitly requests a feature/fix branch, create one with a descriptive name:
```bash
git checkout -b feat/<short-description>
```
2. If dependencies changed or you are setting up the repo, run `make sync`.
3. Implement changes and add or update tests alongside code updates.
4. Highlight compatibility or API risks in your plan before implementing changes that alter the latest released behavior or a released or explicitly supported durable external state boundary.
5. Build docs when you touch documentation:
3. If dependencies changed or you are setting up the repo, run `make sync`.
4. Implement changes and add or update tests alongside code updates.
5. Highlight compatibility or API risks in your plan before implementing changes that alter the latest released behavior or a released or explicitly supported durable external state boundary.
6. Build docs when you touch documentation:
```bash
make build-docs
```
6. When `$code-change-verification` applies, run it to execute the full verification stack before marking work complete.
7. Commit with concise, imperative messages; keep commits small and focused, then open a pull request.
8. When reporting code changes as complete (after substantial code work), invoke `$pr-draft-summary` as the final handoff step unless the task falls under the documented skip cases.
7. When `$code-change-verification` applies, run it to execute the full verification stack before marking work complete.
8. Commit with concise, imperative messages; keep commits small and focused, then open a pull request.
9. Before reporting eligible code changes as complete, invoke `$pr-draft-summary` as the final handoff step unless the task falls under the documented skip cases. Do not omit it based on perceived change size or because the work remains local or uncommitted.
### Testing & Automated Checks
-1
View File
@@ -1 +0,0 @@
Read the AGENTS.md file for instructions.
Symlink
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+79 -9
View File
@@ -10,13 +10,14 @@ The OpenAI Agents SDK is a lightweight yet powerful framework for building multi
### Core concepts:
1. [**Agents**](https://openai.github.io/openai-agents-python/agents): LLMs configured with instructions, tools, guardrails, and handoffs
1. [**Sandbox Agents**](https://openai.github.io/openai-agents-python/sandbox_agents): Agents preconfigured to work with a container to perform work over long time horizons.
1. **[Agents as tools](https://openai.github.io/openai-agents-python/tools/#agents-as-tools) / [Handoffs](https://openai.github.io/openai-agents-python/handoffs/)**: Delegating to other agents for specific tasks
1. [**Tools**](https://openai.github.io/openai-agents-python/tools/): Various Tools let agents take actions (functions, MCP, hosted tools)
1. [**Guardrails**](https://openai.github.io/openai-agents-python/guardrails/): Configurable safety checks for input and output validation
1. [**Human in the loop**](https://openai.github.io/openai-agents-python/human_in_the_loop/): Built-in mechanisms for involving humans across agent runs
1. [**Sessions**](https://openai.github.io/openai-agents-python/sessions/): Automatic conversation history management across agent runs
1. [**Tracing**](https://openai.github.io/openai-agents-python/tracing/): Built-in tracking of agent runs, allowing you to view, debug and optimize your workflows
1. [**Realtime Agents**](https://openai.github.io/openai-agents-python/realtime/quickstart/): Build powerful voice agents with `gpt-realtime-1.5` and full agent features
1. [**Realtime Agents**](https://openai.github.io/openai-agents-python/realtime/quickstart/): Build powerful voice agents with `gpt-realtime-2.1` and full agent features
Explore the [examples](https://github.com/openai/openai-agents-python/tree/main/examples) directory to see the SDK in action, and read our [documentation](https://openai.github.io/openai-agents-python/) for more details.
@@ -45,7 +46,38 @@ uv add openai-agents
For voice support, install with the optional `voice` group: `uv add 'openai-agents[voice]'`. For Redis session support, install with the optional `redis` group: `uv add 'openai-agents[redis]'`.
## Run your first agent
## Run your first agents
The SDK supports three primary ways to run agents. Set the `OPENAI_API_KEY` environment variable before running any of these examples.
### Run a sandbox agent
Use a [`SandboxAgent`](https://openai.github.io/openai-agents-python/sandbox_agents) when the agent needs to inspect files, run commands, apply patches, or preserve workspace state across longer tasks.
```python
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import GitRepo
from agents.sandbox.sandboxes import UnixLocalSandboxClient
agent = SandboxAgent(
name="Workspace Assistant",
instructions="Inspect the sandbox workspace before answering.",
default_manifest=Manifest(entries={"repo": GitRepo(repo="openai/openai-agents-python", ref="main")}),
)
result = Runner.run_sync(
agent,
"Inspect the repo README and summarize what this project does.",
run_config=RunConfig(sandbox=SandboxRunConfig(client=UnixLocalSandboxClient())),
)
print(result.final_output)
```
### Run a text agent
Use a text `Agent` for workflows that do not need a persistent realtime connection or a sandbox workspace.
```python
from agents import Agent, Runner
@@ -60,20 +92,58 @@ print(result.final_output)
# Infinite loop's dance.
```
(_If running this, ensure you set the `OPENAI_API_KEY` environment variable_)
(_For Jupyter notebook users, see [hello_world_jupyter.ipynb](https://github.com/openai/openai-agents-python/blob/main/examples/basic/hello_world_jupyter.ipynb)_)
### Run a realtime agent
Use a [`RealtimeAgent`](https://openai.github.io/openai-agents-python/realtime/quickstart/) for low-latency, server-side voice and multimodal experiences over WebSocket.
```python
import asyncio
from agents.realtime import RealtimeAgent, RealtimeRunner
async def main() -> None:
agent = RealtimeAgent(name="Assistant", instructions="You are a helpful voice assistant. Keep responses short.")
runner = RealtimeRunner(starting_agent=agent)
session = await runner.run()
async with session:
await session.send_message("Say hello in one short sentence.")
async for event in session:
if event.type == "audio":
# Forward or play event.audio.data.
pass
elif event.type == "history_added":
print(event.item)
elif event.type == "agent_end":
break
if __name__ == "__main__":
asyncio.run(main())
```
Explore the [examples](https://github.com/openai/openai-agents-python/tree/main/examples) directory to see the SDK in action, and read our [documentation](https://openai.github.io/openai-agents-python/) for more details.
## Acknowledgements
We'd like to acknowledge the excellent work of the open-source community, especially:
- [Pydantic](https://docs.pydantic.dev/latest/) (data validation) and [PydanticAI](https://ai.pydantic.dev/) (advanced agent framework)
- [LiteLLM](https://github.com/BerriAI/litellm) (unified interface for 100+ LLMs)
- [MkDocs](https://github.com/squidfunk/mkdocs-material)
- [Griffe](https://github.com/mkdocstrings/griffe)
- [uv](https://github.com/astral-sh/uv) and [ruff](https://github.com/astral-sh/ruff)
- [Pydantic](https://docs.pydantic.dev/latest/)
- [Requests](https://github.com/psf/requests)
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
- [Griffe](https://github.com/mkdocstrings/griffe)
This library has these optional dependencies:
- [websockets](https://github.com/python-websockets/websockets)
- [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy)
- [any-llm](https://github.com/mozilla-ai/any-llm) and [LiteLLM](https://github.com/BerriAI/litellm)
We also rely on the following tools to manage the project:
- [uv](https://github.com/astral-sh/uv) and [ruff](https://github.com/astral-sh/ruff)
- [mypy](https://github.com/python/mypy) and [Pyright](https://github.com/microsoft/pyright)
- [pytest](https://github.com/pytest-dev/pytest) and [Coverage.py](https://github.com/coveragepy/coveragepy)
- [MkDocs](https://github.com/squidfunk/mkdocs-material)
We're committed to continuing to build the Agents SDK as an open source framework so others in the community can expand on our approach.
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
For a more in-depth look at our security policy, please check out our [Coordinated Vulnerability Disclosure Policy](https://openai.com/security/disclosure/#:~:text=Disclosure%20Policy,-Security%20is%20essential&text=OpenAI%27s%20coordinated%20vulnerability%20disclosure%20policy,expect%20from%20us%20in%20return.).
Our PGP key can located [at this address.](https://cdn.openai.com/security.txt)
+9 -4
View File
@@ -2,7 +2,9 @@
Agents are the core building block in your apps. An agent is a large language model (LLM) configured with instructions, tools, and optional runtime behavior such as handoffs, guardrails, and structured outputs.
Use this page when you want to define or customize a single agent. If you are deciding how multiple agents should collaborate, read [Agent orchestration](multi_agent.md).
Use this page when you want to define or customize a single plain `Agent`. If you are deciding how multiple agents should collaborate, read [Agent orchestration](multi_agent.md). If the agent should run inside an isolated workspace with manifest-defined files and sandbox-native capabilities, read [Sandbox agent concepts](sandbox/guide.md).
The SDK uses the Responses API by default for OpenAI models, but the distinction here is orchestration: `Agent` plus `Runner` lets the SDK manage turns, tools, guardrails, handoffs, and sessions for you. If you want to own that loop yourself, use the Responses API directly instead.
## Choose the next guide
@@ -12,6 +14,7 @@ Use this page as the hub for agent definition. Jump to the adjacent guide that m
| --- | --- |
| Choose a model or provider setup | [Models](models/index.md) |
| Add capabilities to the agent | [Tools](tools.md) |
| Run an agent against a real repo, document bundle, or isolated workspace | [Sandbox agents quickstart](sandbox_agents.md) |
| Decide between manager-style orchestration and handoffs | [Agent orchestration](multi_agent.md) |
| Configure handoff behavior | [Handoffs](handoffs.md) |
| Run turns, stream events, or manage conversation state | [Running agents](running_agents.md) |
@@ -25,7 +28,7 @@ The most common properties of an agent are:
| Property | Required | Description |
| --- | --- | --- |
| `name` | yes | Human-readable agent name. |
| `instructions` | yes | System prompt or dynamic instructions callback. See [Dynamic instructions](#dynamic-instructions). |
| `instructions` | no | System prompt or dynamic instructions callback. Strongly recommended. See [Dynamic instructions](#dynamic-instructions). |
| `prompt` | no | OpenAI Responses API prompt configuration. Accepts a static prompt object or a function. See [Prompt templates](#prompt-templates). |
| `handoff_description` | no | Short description exposed when this agent is offered as a handoff target. |
| `handoffs` | no | Delegate the conversation to specialist agents. See [handoffs](handoffs.md). |
@@ -57,6 +60,8 @@ agent = Agent(
)
```
Everything in this section applies to `Agent`. `SandboxAgent` builds on the same ideas, then adds `default_manifest`, `base_instructions`, `capabilities`, and `run_as` for workspace-scoped runs. See [Sandbox agent concepts](sandbox/guide.md).
## Prompt templates
You can reference a prompt template created in the OpenAI platform by setting `prompt`. This works with OpenAI models using the Responses API.
@@ -256,7 +261,7 @@ Typical hook timing:
- `on_agent_start` / `on_agent_end`: when a specific agent begins or finishes producing a final output.
- `on_llm_start` / `on_llm_end`: immediately around each model call.
- `on_tool_start` / `on_tool_end`: around each local tool invocation.
- `on_tool_start` / `on_tool_end`: around each local tool invocation. For function tools, the hook `context` is typically a `ToolContext`, so you can inspect tool-call metadata such as `tool_call_id`.
- `on_handoff`: when control moves from one agent to another.
Use `RunHooks` when you want a single observer for the whole workflow, and `AgentHooks` when one agent needs custom side effects.
@@ -295,7 +300,7 @@ By using the `clone()` method on an agent, you can duplicate an Agent, and optio
pirate_agent = Agent(
name="Pirate",
instructions="Write like a pirate",
model="gpt-5.4",
model="gpt-5.6-sol",
)
robot_agent = pirate_agent.clone(
Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

+58
View File
@@ -2,9 +2,13 @@
This page covers SDK-wide defaults that you usually set once during application startup, such as the default OpenAI key or client, the default OpenAI API shape, tracing export defaults, and logging behavior.
These defaults still apply to sandbox-based workflows, but sandbox workspaces, sandbox clients, and session reuse are configured separately.
If you need to configure a specific agent or run instead, start with:
- [Agents](agents.md) for instructions, tools, output types, handoffs, and guardrails on a plain `Agent`.
- [Running agents](running_agents.md) for `RunConfig`, sessions, and conversation-state options.
- [Sandbox agents](sandbox/guide.md) for `SandboxRunConfig`, manifests, capabilities, and sandbox-client-specific workspace setup.
- [Models](models/index.md) for model selection and provider configuration.
- [Tracing](tracing.md) for per-run tracing metadata and custom trace processors.
@@ -28,6 +32,13 @@ custom_client = AsyncOpenAI(base_url="...", api_key="...")
set_default_openai_client(custom_client)
```
If you prefer environment-based endpoint configuration, the default OpenAI provider also reads `OPENAI_BASE_URL`. When you enable Responses websocket transport, it also reads `OPENAI_WEBSOCKET_BASE_URL` for the websocket `/responses` endpoint.
```bash
export OPENAI_BASE_URL="https://your-openai-compatible-endpoint.example/v1"
export OPENAI_WEBSOCKET_BASE_URL="wss://your-openai-compatible-endpoint.example/v1"
```
Finally, you can also customize the OpenAI API that is used. By default, we use the OpenAI Responses API. You can override this to use the Chat Completions API by using the [set_default_openai_api()][agents.set_default_openai_api] function.
```python
@@ -36,6 +47,38 @@ from agents import set_default_openai_api
set_default_openai_api("chat_completions")
```
## OpenAI provider defaults
OpenAI-backed providers also read SDK-wide defaults when they resolve model names. Use [`set_default_openai_responses_transport()`][agents.set_default_openai_responses_transport] to make OpenAI Responses models use websocket transport by default:
```python
from agents import set_default_openai_responses_transport
set_default_openai_responses_transport("websocket")
```
This affects OpenAI Responses models resolved by the default OpenAI provider. For provider-level setup, connection reuse, keepalive options, and custom websocket endpoints, see [Responses WebSocket transport](models/index.md#responses-websocket-transport).
If your OpenAI setup expects provider-level agent registration metadata, configure a default harness ID once at startup:
```python
from agents import set_default_openai_harness
set_default_openai_harness("your-harness-id")
```
You can also pass the full registration object:
```python
from agents import OpenAIAgentRegistrationConfig, set_default_openai_agent_registration
set_default_openai_agent_registration(
OpenAIAgentRegistrationConfig(harness_id="your-harness-id")
)
```
If no SDK default is set, OpenAI-backed providers fall back to the `OPENAI_AGENT_HARNESS_ID` environment variable. When a harness ID is configured, the SDK adds it to trace metadata as `agent_harness_id` unless that key is already present in `RunConfig.trace_metadata`.
## Tracing
Tracing is enabled by default. By default it uses the same OpenAI API key as your model requests from the section above (that is, the environment variable or the default key you set). You can specifically set the API key used for tracing by using the [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] function.
@@ -46,6 +89,21 @@ from agents import set_tracing_export_api_key
set_tracing_export_api_key("sk-...")
```
If your model traffic uses one key or client but tracing should use a different OpenAI key, pass `use_for_tracing=False` when setting the default key or client, then configure tracing separately. The same pattern works with [`set_default_openai_key()`][agents.set_default_openai_key] if you are not using a custom client.
```python
from openai import AsyncOpenAI
from agents import (
set_default_openai_client,
set_tracing_export_api_key,
)
custom_client = AsyncOpenAI(base_url="https://your-openai-compatible-endpoint.example/v1", api_key="provider-key")
set_default_openai_client(custom_client, use_for_tracing=False)
set_tracing_export_api_key("sk-tracing")
```
If you need to attribute traces to a specific organization or project when using the default exporter, set these environment variables before your app starts:
```bash
+2
View File
@@ -13,6 +13,8 @@ This is represented via the [`RunContextWrapper`][agents.run_context.RunContextW
2. You pass that object to the various run methods (e.g. `Runner.run(..., context=whatever)`).
3. All your tool calls, lifecycle hooks etc will be passed a wrapper object, `RunContextWrapper[T]`, where `T` represents your context object type which you can access via `wrapper.context`.
For some runtime-specific callbacks, the SDK may pass a more specialized subclass of `RunContextWrapper[T]`. For example, function-tool lifecycle hooks typically receive `ToolContext`, which also exposes tool-call metadata like `tool_call_id`, `tool_name`, and `tool_arguments`.
The **most important** thing to be aware of: every agent, tool function, lifecycle etc for a given agent run must use the same _type_ of context.
You can use the context for things like:
+58 -29
View File
@@ -4,58 +4,73 @@ Check out a variety of sample implementations of the SDK in the examples section
## Categories
- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):**
Examples in this category illustrate common agent design patterns, such as
- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** Examples in this category illustrate common agent design patterns, such as
- Deterministic workflows
- Agents as tools
- Agents as tools with streaming events (`examples/agent_patterns/agents_as_tools_streaming.py`)
- Agents as tools with structured input parameters (`examples/agent_patterns/agents_as_tools_structured.py`)
- Parallel agent execution
- Conditional tool usage
- Forcing tool use with different behaviors (`examples/agent_patterns/forcing_tool_use.py`)
- Input/output guardrails
- LLM as a judge
- Routing
- Streaming guardrails
- Human-in-the-loop with tool approval and state serialization (`examples/agent_patterns/human_in_the_loop.py`)
- Human-in-the-loop with streaming (`examples/agent_patterns/human_in_the_loop_stream.py`)
- Custom rejection messages for approval flows (`examples/agent_patterns/human_in_the_loop_custom_rejection.py`)
- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):**
These examples showcase foundational capabilities of the SDK, such as
- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** These examples showcase foundational capabilities of the SDK, such as
- Hello world examples (Default model, GPT-5, open-weight model)
- Agent lifecycle management
- Run hooks and agent hooks lifecycle example (`examples/basic/lifecycle_example.py`)
- Dynamic system prompts
- Basic tool usage (`examples/basic/tools.py`)
- Tool input/output guardrails (`examples/basic/tool_guardrails.py`)
- Image tool output (`examples/basic/image_tool_output.py`)
- Streaming outputs (text, items, function call args)
- Responses websocket transport with a shared session helper across turns (`examples/basic/stream_ws.py`)
- Prompt templates
- File handling (local and remote, images and PDFs)
- Usage tracking
- Runner-managed retry settings (`examples/basic/retry.py`)
- Runner-managed retries with LiteLLM (`examples/basic/retry_litellm.py`)
- Runner-managed retries through a third-party adapter (`examples/basic/retry_litellm.py`)
- Non-strict output types
- Previous response ID usage
- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):**
Example customer service system for an airline.
- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** Example customer service system for an airline.
- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):**
A financial research agent that demonstrates structured research workflows with agents and tools for financial data analysis.
- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** A financial research agent that demonstrates structured research workflows with agents and tools for financial data analysis.
- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):**
See practical examples of agent handoffs with message filtering.
- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** Practical examples of agent handoffs with message filtering, including:
- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):**
Examples demonstrating how to use hosted MCP (Model Context Protocol) connectors and approvals.
- Message filter example (`examples/handoffs/message_filter.py`)
- Message filter with streaming (`examples/handoffs/message_filter_streaming.py`)
- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):**
Learn how to build agents with MCP (Model Context Protocol), including:
- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** Examples demonstrating how to use hosted MCP (Model Context Protocol) with the OpenAI Responses API, including:
- Simple hosted MCP without approval (`examples/hosted_mcp/simple.py`)
- MCP connectors such as Google Calendar (`examples/hosted_mcp/connectors.py`)
- Human-in-the-loop with interruption-based approvals (`examples/hosted_mcp/human_in_the_loop.py`)
- On-approval callback for MCP tool calls (`examples/hosted_mcp/on_approval.py`)
- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** Learn how to build agents with MCP (Model Context Protocol), including:
- Filesystem examples
- Git examples
- MCP prompt server examples
- SSE (Server-Sent Events) examples
- SSE remote server connection (`examples/mcp/sse_remote_example`)
- Streamable HTTP examples
- Streamable HTTP remote connection (`examples/mcp/streamable_http_remote_example`)
- Custom HTTP client factory for Streamable HTTP (`examples/mcp/streamablehttp_custom_client_example`)
- Prefetching all MCP tools with `MCPUtil.get_all_function_tools` (`examples/mcp/get_all_mcp_tools_example`)
- MCPServerManager with FastAPI (`examples/mcp/manager_example`)
- MCP tool filtering (`examples/mcp/tool_filter_example`)
- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):**
Examples of different memory implementations for agents, including:
- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** Examples of different memory implementations for agents, including:
- SQLite session storage
- Advanced SQLite session storage
@@ -66,30 +81,45 @@ Check out a variety of sample implementations of the SDK in the examples section
- OpenAI Conversations session storage
- Responses compaction session storage
- Stateless Responses compaction with `ModelSettings(store=False)` (`examples/memory/compaction_session_stateless_example.py`)
- File-backed session storage (`examples/memory/file_session.py`)
- File-backed session with human-in-the-loop (`examples/memory/file_hitl_example.py`)
- SQLite in-memory session with human-in-the-loop (`examples/memory/memory_session_hitl_example.py`)
- OpenAI Conversations session with human-in-the-loop (`examples/memory/openai_session_hitl_example.py`)
- HITL approval/rejection scenario across sessions (`examples/memory/hitl_session_scenario.py`)
- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):**
Explore how to use non-OpenAI models with the SDK, including custom providers and LiteLLM integration.
- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** Explore how to use non-OpenAI models with the SDK, including custom providers and third-party adapters.
- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):**
Examples showing how to build real-time experiences using the SDK, including:
- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** Examples showing how to build real-time experiences using the SDK, including:
- Web application patterns with structured text and image messages
- Command-line audio loops and playback handling
- Twilio Media Streams integration over WebSocket
- Twilio SIP integration using Realtime Calls API attach flows
- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):**
Examples demonstrating how to work with reasoning content and structured outputs.
- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** Examples demonstrating how to work with reasoning content, including:
- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):**
Simple deep research clone that demonstrates complex multi-agent research workflows.
- Reasoning content with the Runner API, streaming and non-streaming (`examples/reasoning_content/runner_example.py`)
- Reasoning content with OSS models via OpenRouter (`examples/reasoning_content/gpt_oss_stream.py`)
- Basic reasoning content example (`examples/reasoning_content/main.py`)
- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):**
Learn how to implement OAI hosted tools and experimental Codex tooling such as:
- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** Simple deep research clone that demonstrates complex multi-agent research workflows.
- **[sandbox](https://github.com/openai/openai-agents-python/tree/main/examples/sandbox):** Examples for running agents in isolated workspaces, including:
- Basic sandbox agent setup (`examples/sandbox/basic.py`)
- Unix-local and Docker sandbox lifecycle examples
- Sandbox-backed handoffs (`examples/sandbox/handoffs.py`)
- Sandbox memory and snapshot resume (`examples/sandbox/memory.py`)
- Sandbox agents exposed as tools (`examples/sandbox/sandbox_agents_as_tools.py`)
- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** Learn how to implement OAI hosted tools and experimental Codex tooling such as:
- Web search and web search with filters
- File search
- Code interpreter
- Apply patch tool with file editing and approval (`examples/tools/apply_patch.py`)
- Shell tool execution with approval callbacks (`examples/tools/shell.py`)
- Shell tool with human-in-the-loop interruption-based approvals (`examples/tools/shell_human_in_the_loop.py`)
- Hosted container shell with inline skills (`examples/tools/container_shell_inline_skill.py`)
- Hosted container shell with skill references (`examples/tools/container_shell_skill_reference.py`)
- Local shell with local skills (`examples/tools/local_shell_skill.py`)
@@ -99,5 +129,4 @@ Check out a variety of sample implementations of the SDK in the examples section
- Experimental Codex tool workflows (`examples/tools/codex.py`)
- Experimental Codex same-thread workflows (`examples/tools/codex_same_thread.py`)
- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):**
See examples of voice agents, using our TTS and STT models, including streamed voice examples.
- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** See examples of voice agents, using our TTS and STT models, including streamed voice examples.
+1
View File
@@ -57,6 +57,7 @@ Tool guardrails wrap **function tools** and let you validate or block tool calls
- Input tool guardrails run before the tool executes and can skip the call, replace the output with a message, or raise a tripwire.
- Output tool guardrails run after the tool executes and can replace the output or raise a tripwire.
- If a function tool requires approval, input tool guardrails normally run after approval and immediately before execution. Set [`RunConfig.tool_execution`][agents.run.RunConfig.tool_execution] to [`ToolExecutionConfig(pre_approval_tool_input_guardrails=True)`][agents.run.ToolExecutionConfig] when you want those input checks to run before the pending approval interruption is emitted. Calls that pass this pre-approval check are still checked again after approval before the tool executes.
- Tool guardrails apply only to function tools created with [`function_tool`][agents.tool.function_tool]. Handoffs run through the SDK's handoff pipeline rather than the normal function-tool pipeline, so tool guardrails do not apply to the handoff call itself. Hosted tools (`WebSearchTool`, `FileSearchTool`, `HostedMCPTool`, `CodeInterpreterTool`, `ImageGenerationTool`) and built-in execution tools (`ComputerTool`, `ShellTool`, `ApplyPatchTool`, `LocalShellTool`) also do not use this guardrail pipeline, and [`Agent.as_tool()`][agents.agent.Agent.as_tool] does not currently expose tool-guardrail options directly.
See the code snippet below for details.
+2 -2
View File
@@ -61,7 +61,7 @@ handoff_obj = handoff(
## Handoff inputs
In certain situations, you want the LLM to provide some data when it calls a handoff. For example, imagine a handoff to an "Escalation agent". You might want a reason to be provided, so you can log it.
In certain situations, you want the LLM to provide some data when it calls a handoff. For example, imagine a handoff to an "Escalation agent". You might want the model to provide a reason so you can log it.
```python
from pydantic import BaseModel
@@ -112,7 +112,7 @@ When a handoff occurs, it's as though the new agent takes over the conversation,
- `input_items`: optional items to forward to the next agent instead of `new_items`, allowing you to filter model input while keeping `new_items` intact for session history.
- `run_context`: the active [`RunContextWrapper`][agents.run_context.RunContextWrapper] at the time the handoff was invoked.
Nested handoffs are available as an opt-in beta and are disabled by default while we stabilize them. When you enable [`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history], the runner collapses the prior transcript into a single assistant summary message and wraps it in a `<CONVERSATION HISTORY>` block that keeps appending new turns when multiple handoffs happen during the same run. You can provide your own mapping function via [`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] to replace the generated message without writing a full `input_filter`. The opt-in only applies when neither the handoff nor the run supplies an explicit `input_filter`, so existing code that already customizes the payload (including the examples in this repository) keeps its current behavior without changes. You can override the nesting behaviour for a single handoff by passing `nest_handoff_history=True` or `False` to [`handoff(...)`][agents.handoffs.handoff], which sets [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history]. If you just need to change the wrapper text for the generated summary, call [`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] (and optionally [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers]) before running your agents.
Nested handoffs are available as an opt-in beta and are disabled by default while we stabilize them. When you enable [`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history], the built-in behavior compacts the prior transcript into one or more assistant summary messages wrapped in `<CONVERSATION HISTORY>` blocks. Lossless message items remain between those summary segments in their original positions, so the next agent receives the same chronology without duplicate representations. You can provide your own mapping function via [`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] to replace the built-in ordered input without writing a full `input_filter`; the mapper's returned list becomes the exact input history. The opt-in only applies when neither the handoff nor the run supplies an explicit `input_filter`, so existing code that already customizes the payload (including the examples in this repository) keeps its current behavior without changes. You can override the nesting behaviour for a single handoff by passing `nest_handoff_history=True` or `False` to [`handoff(...)`][agents.handoffs.handoff], which sets [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history]. If you just need to change the wrapper text used by built-in summary segments, call [`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] (and optionally [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers]) before running your agents.
If both the handoff and the active [`RunConfig.handoff_input_filter`][agents.run.RunConfig.handoff_input_filter] define a filter, the per-handoff [`input_filter`][agents.handoffs.Handoff.input_filter] takes precedence for that specific handoff.
+4 -12
View File
@@ -186,19 +186,11 @@ Useful serialization options:
- `context_serializer`: Customize how non-mapping context objects are serialized.
- `context_deserializer`: Rebuild non-mapping context objects when loading state with `RunState.from_json(...)` or `RunState.from_string(...)`.
- `strict_context=True`: Fail serialization or deserialization unless the context is already a
mapping or you provide the appropriate serializer/deserializer.
- `context_override`: Replace the serialized context when loading state. This is useful when you
do not want to restore the original context object, but it does not remove that context from an
already serialized payload.
- `include_tracing_api_key=True`: Include the tracing API key in the serialized trace payload
when you need resumed work to keep exporting traces with the same credentials.
- `strict_context=True`: Fail serialization or deserialization unless the context is already a mapping or you provide the appropriate serializer/deserializer.
- `context_override`: Replace the serialized context when loading state. This is useful when you do not want to restore the original context object, but it does not remove that context from an already serialized payload.
- `include_tracing_api_key=True`: Include the tracing API key in the serialized trace payload when you need resumed work to keep exporting traces with the same credentials.
Serialized run state includes your app context plus SDK-managed runtime metadata such as approvals,
usage, serialized `tool_input`, nested agent-as-tool resumptions, trace metadata, and server-managed
conversation settings. If you plan to store or transmit serialized state, treat
`RunContextWrapper.context` as persisted data and avoid placing secrets there unless you
intentionally want them to travel with the state.
Serialized run state includes your app context plus SDK-managed runtime metadata such as approvals, usage, serialized `tool_input`, nested agent-as-tool resumptions, trace metadata, and server-managed conversation settings. If you plan to store or transmit serialized state, treat `RunContextWrapper.context` as persisted data and avoid placing secrets there unless you intentionally want them to travel with the state.
## Versioning pending tasks
+22 -2
View File
@@ -20,13 +20,31 @@ Here are the main features of the SDK:
- **Agent loop**: A built-in agent loop that handles tool invocation, sends results back to the LLM, and continues until the task is complete.
- **Python-first**: Use built-in language features to orchestrate and chain agents, rather than needing to learn new abstractions.
- **Agents as tools / Handoffs**: A powerful mechanism for coordinating and delegating work across multiple agents.
- **Sandbox agents**: Run specialists inside real isolated workspaces with manifest-defined files, sandbox client choice, and resumable sandbox sessions.
- **Guardrails**: Run input validation and safety checks in parallel with agent execution, and fail fast when checks do not pass.
- **Function tools**: Turn any Python function into a tool with automatic schema generation and Pydantic-powered validation.
- **MCP server tool calling**: Built-in MCP server tool integration that works the same way as function tools.
- **Sessions**: A persistent memory layer for maintaining working context within an agent loop.
- **Human in the loop**: Built-in mechanisms for involving humans across agent runs.
- **Tracing**: Built-in tracing for visualizing, debugging, and monitoring workflows, with support for the OpenAI suite of evaluation, fine-tuning, and distillation tools.
- **Realtime Agents**: Build powerful voice agents with `gpt-realtime-1.5`, automatic interruption detection, context management, guardrails, and more.
- **Realtime Agents**: Build powerful voice agents with `gpt-realtime-2.1`, automatic interruption detection, context management, guardrails, and more.
## Agents SDK or Responses API?
The SDK uses the Responses API by default for OpenAI models, but it adds a higher-level runtime around model calls.
Use the Responses API directly when:
- you want to own the loop, tool dispatch, and state handling yourself
- your workflow is short-lived and mainly about returning the model's response
Use the Agents SDK when:
- you want the runtime to manage turns, tool execution, guardrails, handoffs, or sessions
- your agent should produce artifacts or operate across multiple coordinated steps
- you need a real workspace or resumable execution through [Sandbox agents](sandbox_agents.md)
You do not need to choose one globally. Many applications use the SDK for managed workflows and call the Responses API directly for lower-level paths.
## Installation
@@ -59,6 +77,7 @@ export OPENAI_API_KEY=sk-...
- Build your first text-based agent with the [Quickstart](quickstart.md).
- Then decide how you want to carry state across turns in [Running agents](running_agents.md#choose-a-memory-strategy).
- If the task depends on real files, repos, or isolated per-agent workspace state, read the [Sandbox agents quickstart](sandbox_agents.md).
- If you are deciding between handoffs and manager-style orchestration, read [Agent orchestration](multi_agent.md).
## Choose your path
@@ -69,9 +88,10 @@ Use this table when you know the job you want to do, but not which page explains
| --- | --- |
| Build the first text agent and see one complete run | [Quickstart](quickstart.md) |
| Add function tools, hosted tools, or agents as tools | [Tools](tools.md) |
| Run a coding, review, or document agent inside a real isolated workspace | [Sandbox agents quickstart](sandbox_agents.md) and [Sandbox clients](sandbox/clients.md) |
| Decide between handoffs and manager-style orchestration | [Agent orchestration](multi_agent.md) |
| Keep memory across turns | [Running agents](running_agents.md#choose-a-memory-strategy) and [Sessions](sessions/index.md) |
| Use OpenAI models, websocket transport, or non-OpenAI providers | [Models](models/index.md) |
| Review outputs, run items, interruptions, and resume state | [Results](results.md) |
| Build a low-latency voice agent with `gpt-realtime-1.5` | [Realtime agents quickstart](realtime/quickstart.md) and [Realtime transport](realtime/transport.md) |
| Build a low-latency voice agent with `gpt-realtime-2.1` | [Realtime agents quickstart](realtime/quickstart.md) and [Realtime transport](realtime/transport.md) |
| Build a speech-to-text / agent / text-to-speech pipeline | [Voice pipeline quickstart](voice/quickstart.md) |
+76 -71
View File
@@ -4,46 +4,49 @@ search:
---
# エージェント
エージェントは、アプリにおける中核的な基本コンポーネントです。エージェントは、大規模言語モデル ( LLM ) に instructions、ツール、さらにハンドオフ、ガードレール、structured outputs などの任意の実行時動作を設定したものです。
エージェントは、アプリの中核となる構成要素です。エージェントは、instructions、ツール、およびハンドオフ、ガードレール、structured outputs などのオプションの実行時動作を設定した大規模言語モデル(LLMです。
このページは、単一のエージェントを定義またはカスタマイズしたい場合に使用します。複数のエージェントをどのように連携させるかを検討している場合は、[エージェントオーケストレーション](multi_agent.md) を参照してください。
単一の標準的な `Agent` を定義またはカスタマイズする場合は、このページを参照してください。複数のエージェントをどのように連携させるかを検討している場合は、[エージェントオーケストレーション](multi_agent.md)を参照してください。マニフェストで定義されたファイルとサンドボックスネイティブの機能を備えた分離ワークスペース内でエージェントを実行する場合は、[サンドボックスエージェントの概念](sandbox/guide.md)を参照してください。
SDK は、OpenAI モデルに対してデフォルトで Responses API を使用しますが、ここでの違いはオーケストレーションにあります。`Agent``Runner` を組み合わせることで、SDK がターン、ツール、ガードレール、ハンドオフ、セッションを管理します。このループを自分で管理したい場合は、代わりに Responses API を直接使用してください。
## 次のガイドの選択
このページをエージェント定義のハブとして使用してください。次に必要な判断に対応する隣接ガイドへ移動できます
このページをエージェント定義のハブとして使用してください。次に行う必要がある判断に合った関連ガイドに進んでください
| したいこと | 次に読むもの |
| 目的 | 次に読むガイド |
| --- | --- |
| モデルまたはプロバイダー設定を選 | [Models](models/index.md) |
| エージェントに機能を追加する | [Tools](tools.md) |
| マネージャースタイルのオーケストレーションとハンドオフのどちらにするか決める | [エージェントオーケストレーション](multi_agent.md) |
| ハンドオフ動作を設定する | [Handoffs](handoffs.md) |
| ターン実行、イベントのストリーミング、会話状態の管理を行う | [エージェントの実行](running_agents.md) |
| 最終出力、実行項目、再開可能な状態を確認する | [結果](results.md) |
| モデルまたはプロバイダー設定を選択する | [モデル](models/index.md) |
| エージェントに機能を追加する | [ツール](tools.md) |
| 実際のリポジトリ、ドキュメント一式、または分離ワークスペースを対象にエージェントを実行する | [サンドボックスエージェントのクイックスタート](sandbox_agents.md) |
| マネージャー形式のオーケストレーションとハンドオフのどちらを使用するか決定する | [エージェントオーケストレーション](multi_agent.md) |
| ハンドオフの動作を設定する | [ハンドオフ](handoffs.md) |
| ターンの実行、イベントのストリーミング、または会話状態の管理を行う | [エージェントの実行](running_agents.md) |
| 最終出力、実行項目、または再開可能な状態を確認する | [実行結果](results.md) |
| ローカル依存関係と実行時状態を共有する | [コンテキスト管理](context.md) |
## 基本設定
エージェント最も一般的なプロパティは次のとおりです。
エージェント最も一般的なプロパティは次のとおりです。
| プロパティ | 必須 | 説明 |
| --- | --- | --- |
| `name` | はい | 人が読めるエージェント名です。 |
| `instructions` | い | システムプロンプトまたは動的 instructions コールバックです。[動的 instructions](#dynamic-instructions) を参照してください。 |
| `prompt` | いいえ | OpenAI Responses API のプロンプト設定です。静的なプロンプトオブジェクトまたは関数を受け取ります。[プロンプトテンプレート](#prompt-templates) を参照してください。 |
| `name` | はい | 人が理解しやすいエージェント名です。 |
| `instructions` | いいえ | システムプロンプトまたは動的 instructions コールバックです。使用を強く推奨します。[動的 instructions](#dynamic-instructions)を参照してください。 |
| `prompt` | いいえ | OpenAI Responses API のプロンプト設定です。静的なプロンプトオブジェクトまたは関数を受け取ります。[プロンプトテンプレート](#prompt-templates)を参照してください。 |
| `handoff_description` | いいえ | このエージェントがハンドオフ先として提示される際に公開される短い説明です。 |
| `handoffs` | いいえ | 会話を専門エージェントに委します。[handoffs](handoffs.md) を参照してください。 |
| `model` | いいえ | 使用する LLM を指定します。[Models](models/index.md) を参照してください。 |
| `handoffs` | いいえ | 会話を専門エージェントに委します。[ハンドオフ](handoffs.md)を参照してください。 |
| `model` | いいえ | 使用する LLM です。[モデル](models/index.md)を参照してください。 |
| `model_settings` | いいえ | `temperature``top_p``tool_choice` などのモデル調整パラメーターです。 |
| `tools` | いいえ | エージェントが呼び出せるツールです。[Tools](tools.md) を参照してください。 |
| `mcp_servers` | いいえ | エージェント向けの MCP ベースのツールです。[MCP ガイド](mcp.md) を参照してください。 |
| `mcp_config` | いいえ | 厳密なスキーマ変換や MCP 障害フォーマットなど、MCP ツールの準備方法を調整します。[MCP ガイド](mcp.md#agent-level-mcp-configuration) を参照してください。 |
| `input_guardrails` | いいえ | このエージェントチェーンの最初のユーザー入力実行されるガードレールです。[Guardrails](guardrails.md) を参照してください。 |
| `output_guardrails` | いいえ | このエージェントの最終出力実行されるガードレールです。[Guardrails](guardrails.md) を参照してください。 |
| `output_type` | いいえ | プレーンテキストの代わりに構造化された出力型を指定します。[出力型](#output-types) を参照してください。 |
| `hooks` | いいえ | エージェントスコープのライフサイクルコールバックです。[ライフサイクルイベント ( hooks )](#lifecycle-events-hooks) を参照してください。 |
| `tool_use_behavior` | いいえ | ツール結果をモデルに戻すか実行を終了するかを制御します。[ツール使用動作](#tool-use-behavior) を参照してください。 |
| `reset_tool_choice` | いいえ | ツール使用ループを避けるため、ツール呼び出し後に `tool_choice` をリセットします ( 既定値: `True` )。[ツール使用の強制](#forcing-tool-use) を参照してください。 |
| `tools` | いいえ | エージェントが呼び出せるツールです。[ツール](tools.md)を参照してください。 |
| `mcp_servers` | いいえ | エージェント向けの MCP ベースのツールです。[MCP ガイド](mcp.md)を参照してください。 |
| `mcp_config` | いいえ | 厳密なスキーマ変換や MCP エラー形式など、MCP ツールの準備方法を詳細に調整します。[MCP ガイド](mcp.md#agent-level-mcp-configuration)を参照してください。 |
| `input_guardrails` | いいえ | このエージェントチェーンの最初のユーザー入力に対して実行されるガードレールです。[ガードレール](guardrails.md)を参照してください。 |
| `output_guardrails` | いいえ | このエージェントの最終出力に対して実行されるガードレールです。[ガードレール](guardrails.md)を参照してください。 |
| `output_type` | いいえ | プレーンテキストの代わりに使用する構造化出力型です。[出力型](#output-types)を参照してください。 |
| `hooks` | いいえ | エージェントスコープのライフサイクルコールバックです。[ライフサイクルイベント(フック)](#lifecycle-events-hooks)を参照してください。 |
| `tool_use_behavior` | いいえ | ツールの実行結果をモデルに戻すか実行を終了するかを制御します。[ツール使用時の動作](#tool-use-behavior)を参照してください。 |
| `reset_tool_choice` | いいえ | ツール使用ループを回避するため、ツール呼び出し後に `tool_choice` をリセットします(デフォルト:`True`。[ツール使用の強制](#forcing-tool-use)を参照してください。 |
```python
from agents import Agent, ModelSettings, function_tool
@@ -61,9 +64,11 @@ agent = Agent(
)
```
このセクションの内容はすべて `Agent` に適用されます。`SandboxAgent` は同じ概念を基盤とし、さらにワークスペーススコープの実行向けに `default_manifest``base_instructions``capabilities``run_as` を追加します。[サンドボックスエージェントの概念](sandbox/guide.md)を参照してください。
## プロンプトテンプレート
`prompt` を設定することで、OpenAI プラットフォームで作成したプロンプトテンプレートを参照できます。これは Responses API を使用する OpenAI モデルで動作します。
`prompt` を設定する、OpenAI プラットフォームで作成したプロンプトテンプレートを参照できます。これはResponses API を使用する OpenAI モデルで機能します。
使用するには、次の手順に従ってください。
@@ -75,7 +80,7 @@ agent = Agent(
Write a poem in {{poem_style}}
```
4. `--prompt-id` フラグを付けて例を実行します。
4. `--prompt-id` フラグを指定してコード例を実行します。
```python
from agents import Agent
@@ -122,9 +127,9 @@ result = await Runner.run(
## コンテキスト
エージェントは `context` 型に対してジェネリックです。コンテキストは依存性注入ツールです。これは、作成して `Runner.run()` に渡すオブジェクトであり、すべてのエージェント、ツール、ハンドオフなどに渡され、エージェント実行依存関係と状態をまとめる入れ物として機能します。コンテキストには任意の Python オブジェクトを渡せます。
エージェントは `context` 型に対してジェネリックです。コンテキストは依存性注入のためのツールです。これは、作成して `Runner.run()` に渡すオブジェクトであり、すべてのエージェント、ツール、ハンドオフなどに渡され、エージェント実行に必要な依存関係と状態をまとめて保持します。任意の Python オブジェクトをコンテキストとして指定できます。
`RunContextWrapper` の完全な仕様、共有使用量トラッキング、ネストされた `tool_input`、シリアライズ時の注意については、[context ガイド](context.md) を参照してください。
`RunContextWrapper` の全機能、共有使用量の追跡、ネストされた `tool_input`、およびシリアライズ時の注意事項については、[コンテキストガイド](context.md)を参照してください。
```python
@dataclass
@@ -143,7 +148,7 @@ agent = Agent[UserContext](
## 出力型
既定では、エージェントはプレーンテキスト ( つまり `str` ) を出力します。エージェントに特定の型の出力を生成させたい場合は、`output_type` パラメーターを使用できます。一般的には [Pydantic](https://docs.pydantic.dev/) オブジェクトが使われますが、Pydantic の [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) でラップできる型であれば、dataclasses、lists、TypedDict など任意の型をサポートしています。
デフォルトでは、エージェントはプレーンテキストつまり `str`)の出力を生成します。エージェントに特定の型の出力を生成させ場合は、`output_type` パラメーターを使用できます。一般的には [Pydantic](https://docs.pydantic.dev/) オブジェクトを使用しますが、Pydantic の [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) でラップできる任意の型(データクラス、リスト、TypedDict などをサポートしています。
```python
from pydantic import BaseModel
@@ -164,20 +169,20 @@ agent = Agent(
!!! note
`output_type` を渡すと、モデルは通常のプレーンテキスト応答ではなく [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使用するようになります。
`output_type` を渡すと、通常のプレーンテキスト応答の代わりに [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使用するようモデルに指示します。
## マルチエージェントシステムの設計パターン
マルチエージェントシステム設計方法は多数ありますが、広く適用可能なパターンとして一般的に次の 2 つがあります。
マルチエージェントシステムにはさまざまな設計方法ありますが、一般的に広く適用できる次の 2 つのパターンが使用されます。
1. Manager ( Agents as tools ): 中央の manager / orchestrator が、ツールとして専門サブエージェントを呼び出し、会話の制御を持します。
2. Handoffs: 同等のエージェント同士が、会話を引き継ぐ専門エージェント制御をハンドオフします。これは分散型です。
1. マネージャー(agents as tools):中央のマネージャー/オーケストレーターが、専門化されたサブエージェントをツールとして呼び出し、会話の制御を持します。
2. ハンドオフ:対等なエージェントが、会話を引き継ぐ専門エージェント制御をハンドオフします。これは分散型のパターンです。
詳細[エージェント構築の実践ガイド](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf) を参照してください。
詳細については、[エージェント構築の実践ガイド](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)を参照してください。
### Manager ( Agents as tools )
### マネージャー(agents as tools
`customer_facing_agent` はすべてのユーザー対を処理し、ツールとして公開された専門サブエージェントを呼び出します。詳しくは [tools](tools.md#agents-as-tools) のドキュメントを参照してください。
`customer_facing_agent` はすべてのユーザー対を処理し、ツールとして公開された専門化されたサブエージェントを呼び出します。詳細については、[ツール](tools.md#agents-as-tools)のドキュメントを参照してください。
```python
from agents import Agent
@@ -206,7 +211,7 @@ customer_facing_agent = Agent(
### ハンドオフ
ハンドオフは、エージェントが委譲できるサブエージェントです。ハンドオフが発生すると、委譲先エージェントが会話履歴を受け取り、会話を引き継ぎます。このパターンにより、単一タスクに特化して高い性能を発揮する、モジュール化された専門エージェント実現できます。詳しくは [handoffs](handoffs.md) のドキュメントを参照してください。
ハンドオフは、エージェントが処理を委任できるサブエージェントです。ハンドオフが発生すると、委任先のエージェントが会話履歴を受け取り、会話を引き継ぎます。このパターンにより、単一タスクに特化しモジュール式の専門エージェント実現できます。詳細については、[ハンドオフ](handoffs.md)のドキュメントを参照してください。
```python
from agents import Agent
@@ -227,7 +232,7 @@ triage_agent = Agent(
## 動的 instructions
ほとんどの場合、エージェント作成時に instructions を指定できます。ただし、関数を介して動的 instructions を指定することもできます。関数はエージェントとコンテキストを受け取り、プロンプトを返す必要があります。通常の関数と `async` 関数の両方使用できます。
ほとんどの場合、エージェント作成時に instructions を指定できます。ただし、関数を介して動的 instructions を指定することもできます。この関数はエージェントとコンテキストを受け取り、プロンプトを返す必要があります。通常の関数と `async` 関数の両方使用できます。
```python
def dynamic_instructions(
@@ -242,28 +247,28 @@ agent = Agent[UserContext](
)
```
## ライフサイクルイベント ( hooks )
## ライフサイクルイベント(フック)
場合によっては、エージェントのライフサイクルを観測したいことがあります。たとえば、イベントログ記録したり、データ事前取得したり、特定イベント発生時の使用状況を記録したりできます。
エージェントのライフサイクルを監視したい場合があります。たとえば、特定のイベントが発生した際に、イベントのログ記録、データ事前取得、または使用量の記録を行う場合があります。
hook のスコープは 2 つあります。
フックには次の 2 つのスコープがあります。
- [`RunHooks`][agents.lifecycle.RunHooks] は、他エージェントへのハンドオフを含む `Runner.run(...)` 呼び出し全体を観測します。
- [`AgentHooks`][agents.lifecycle.AgentHooks] は `agent.hooks` を介して特定のエージェントインスタンスにアタッチされます。
- [`RunHooks`][agents.lifecycle.RunHooks] は、他エージェントへのハンドオフを含む `Runner.run(...)` 呼び出し全体を監視します。
- [`AgentHooks`][agents.lifecycle.AgentHooks] は`agent.hooks` を介して特定のエージェントインスタンスにアタッチされます。
また、コールバックコンテキストイベントに応じて変わります。
コールバックコンテキストも、イベントによって異なります。
- エージェント開始 / 終了 hook は [`AgentHookContext`][agents.run_context.AgentHookContext] を受け取ります。これは元のコンテキストをラップし、共有され実行使用量状態を保持します。
- LLM、ツール、ハンドオフ hook は [`RunContextWrapper`][agents.run_context.RunContextWrapper] を受け取ります。
- エージェント開始/終了フックは [`AgentHookContext`][agents.run_context.AgentHookContext] を受け取ります。これは元のコンテキストをラップし、共有され実行使用量状態を保持します。
- LLM、ツール、ハンドオフのフックは [`RunContextWrapper`][agents.run_context.RunContextWrapper] を受け取ります。
一般的な hook のタイミング:
一般的なフックのタイミングは次のとおりです。
- `on_agent_start` / `on_agent_end`: 特定エージェントが最終出力の生成を開始 / 終了したとき。
- `on_llm_start` / `on_llm_end`: 各モデル呼び出しの直前 / 直後。
- `on_tool_start` / `on_tool_end`: 各ローカルツール呼び出しの前後。
- `on_handoff`: 制御があるエージェントから別のエージェント移るとき。
- `on_agent_start` / `on_agent_end`特定エージェントが最終出力の生成を開始または完了したとき。
- `on_llm_start` / `on_llm_end`各モデル呼び出しの直前直後。
- `on_tool_start` / `on_tool_end`各ローカルツール呼び出しの前後。関数ツールの場合、フックの `context` は通常 `ToolContext` であるため、`tool_call_id` などのツール呼び出しメタデータを確認できます。
- `on_handoff`制御があるエージェントから別のエージェント移るとき。
ワークフロー全体を単一の観測者で扱いたい場合は `RunHooks` を、特定エージェントにカスタム副作用が必要な場合は `AgentHooks` を使用してください。
ワークフロー全体を単一のオブザーバーで監視する場合は `RunHooks` を使用し、1 つのエージェントにカスタム副作用が必要な場合は `AgentHooks` を使用してください。
```python
from agents import Agent, RunHooks, Runner
@@ -285,21 +290,21 @@ result = await Runner.run(agent, "Explain quines", hooks=LoggingHooks())
print(result.final_output)
```
コールバック仕様の全体は、[Lifecycle API リファレンス](ref/lifecycle.md) を参照してください。
コールバックの全機能については、[ライフサイクル API リファレンス](ref/lifecycle.md)を参照してください。
## ガードレール
ガードレールを使用すると、エージェント実行と並行してユーザー入力に対するチェック / バリデーションを実行し、さらに生成後のエージェント出力に対してもチェック / バリデーションを実行できます。たとえば、ユーザー入力とエージェント出力関連性をスクリーニングできます。詳しくは [guardrails](guardrails.md) のドキュメントを参照してください。
ガードレールを使用すると、エージェント実行と並行してユーザー入力に対するチェック/検証を行い、エージェント出力が生成された後にその出力をチェックできます。たとえば、ユーザー入力とエージェント出力関連性のある内容かどうかを検査できます。詳細については、[ガードレール](guardrails.md)のドキュメントを参照してください。
## エージェントの複製 / コピー
## エージェントのクローン作成/コピー
エージェント `clone()` メソッドを使用すると、Agent を複製し、必要に応じて任意のプロパティを変更できます。
エージェント `clone()` メソッドを使用すると、Agent を複製し、必要に応じて任意のプロパティを変更できます。
```python
pirate_agent = Agent(
name="Pirate",
instructions="Write like a pirate",
model="gpt-5.4",
model="gpt-5.6-sol",
)
robot_agent = pirate_agent.clone(
@@ -310,14 +315,14 @@ robot_agent = pirate_agent.clone(
## ツール使用の強制
ツールのリストを指定しても、LLM が必ずツールを使用するとは限りません。[`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] を設定することでツール使用を強制できます。有効な値は次のとおりです。
ツールのリストを指定しても、LLM が必ずツールを使用するとは限りません。[`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] を設定すると、ツール使用を強制できます。有効な値は次のとおりです。
1. `auto`: LLM がツールを使かどうかを判断できます。
2. `required`: LLM にツール使用を必須化します ( ただし、どのツールを使うかは適切に判断できます )
3. `none`: LLM ツールを _使用しない_ ことを必須化します。
4. 特定の文字列 ( 例: `my_tool` ) を設定: LLM にその特定ツール使用を必須化します。
1. `auto`ツールを使用するかどうかを LLM が判断できます。
2. `required`LLM にツール使用を要求します。ただし、どのツールを使用するかは LLM が適切に判断できます。
3. `none`LLM ツールを _使用しない_ よう要求します。
4. `my_tool` などの特定の文字列:LLM にその特定ツール使用するよう要求します。
OpenAI Responses のツール検索を使用する場合、名前付きツール選択にはより厳しい制限があります。`tool_choice` で素の namespace 名や deferred 専用ツールを指定することはできず、`tool_choice="tool_search"` [`ToolSearchTool`][agents.tool.ToolSearchTool] を対象にしません。これらの場合は `auto` または `required` を推奨します。Responses 固有の制約については [Hosted tool search](tools.md#hosted-tool-search) を参照してください。
OpenAI Responses のツール検索を使用する場合、名前付きツール選択にはさらに制限があります。`tool_choice` では、単独の名前空間名や遅延専用ツールを指定できず、`tool_choice="tool_search"` [`ToolSearchTool`][agents.tool.ToolSearchTool] を指定することもできません。このような場合は`auto` または `required` を使用してください。Responses 固有の制約については、[ホスト型ツール検索](tools.md#hosted-tool-search)を参照してください。
```python
from agents import Agent, Runner, function_tool, ModelSettings
@@ -335,12 +340,12 @@ agent = Agent(
)
```
## ツール使用動作
## ツール使用時の動作
`Agent` 設定の `tool_use_behavior` パラメーターは、ツール出力の扱い方を制御します。
`Agent` 設定の `tool_use_behavior` パラメーターは、ツール出力の処理方法を制御します。
- `"run_llm_again"`: 既定値です。ツール実行し、LLM が結果を処理して最終応答を生成します。
- `"stop_on_first_tool"`: 最初のツール呼び出しの出力を、そのまま最終応答として使用し、以降の LLM 処理は行いません
- `"run_llm_again"`:デフォルトです。ツール実行され、その実行結果を LLM が処理して最終応答を生成します。
- `"stop_on_first_tool"`最初のツール呼び出しの出力を、それ以降の LLM 処理を行わずに最終応答として使用します
```python
from agents import Agent, Runner, function_tool, ModelSettings
@@ -358,7 +363,7 @@ agent = Agent(
)
```
- `StopAtTools(stop_at_tool_names=[...])`: 指定したいずれかのツールが呼び出された場合に停止し、その出力を最終応答として使用します。
- `StopAtTools(stop_at_tool_names=[...])`指定したツールのいずれかが呼び出された場合に停止し、その出力を最終応答として使用します。
```python
from agents import Agent, Runner, function_tool
@@ -382,7 +387,7 @@ agent = Agent(
)
```
- `ToolsToFinalOutputFunction`: ツール結果を処理し、停止するか LLM で続行するかを判断するカスタム関数です。
- `ToolsToFinalOutputFunction`ツールの実行結果を処理し、停止するか LLM での処理を続けるかを判断するカスタム関数です。
```python
from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper
@@ -420,4 +425,4 @@ agent = Agent(
!!! note
無限ループを防ぐため、フレームワークはツール呼び出し後に `tool_choice` を自動的に "auto" にリセットします。この動作は [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] で設定可能です。無限ループは、ツール結果が LLM に送れ、その後 `tool_choice` により別のツール呼び出し生成される、という流れが無限に続くことで発生します。
無限ループを防ぐため、フレームワークはツール呼び出し後に `tool_choice` を自動的に `"auto"` にリセットします。この動作は [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] で設定できます。無限ループが発生するのは、ツールの実行結果が LLM に送信され、その後 `tool_choice` によって LLM が再びツール呼び出し生成し、この処理が際限なく繰り返されるためです。
+79 -21
View File
@@ -4,17 +4,21 @@ search:
---
# 設定
このページでは、デフォルトの OpenAI キークライアント、デフォルトの OpenAI API 形式、トレーシングエクスポート既定値、ロギングの動作など、通常はアプリケーション起動時に一度だけ設定する SDK 全体のデフォルトについて説明します。
このページでは、デフォルトの OpenAI キーまたはクライアント、デフォルトの OpenAI API 形式、トレーシングエクスポートのデフォルト、ログ動作など、通常はアプリケーション起動時に一度だけ設定する SDK 全体のデフォルトについて説明します。
代わりに特定のエージェントや実行を設定する必要がある場合は、次から始めてください
これらのデフォルトはサンドボックスベースのワークフローにも引き続き適用されますが、サンドボックスワークスペース、サンドボックスクライアント、セッションの再利用は別途設定します
- `RunConfig`、セッション、会話状態オプションについては [エージェントの実行](running_agents.md)。
- モデル選択とプロバイダー設定については [モデル](models/index.md)。
- 実行ごとのトレーシングメタデータとカスタムトレースプロセッサーについては [トレーシング](tracing.md)
代わりに特定のエージェントまたは実行を設定する必要がある場合は、まず次を参照してください:
- [エージェント](agents.md): 通常の `Agent` の instructions、tools、出力タイプ、ハンドオフ、ガードレールについて
- [エージェントの実行](running_agents.md): `RunConfig`、セッション、会話状態オプションについて。
- [サンドボックスエージェント](sandbox/guide.md): `SandboxRunConfig`、マニフェスト、ケイパビリティ、サンドボックスクライアント固有のワークスペース設定について。
- [モデル](models/index.md): モデル選択とプロバイダー設定について。
- [トレーシング](tracing.md): 実行ごとのトレーシングメタデータとカスタムトレースプロセッサーについて。
## API キーとクライアント
デフォルトでは、 SDK は LLM リクエストとトレーシングに `OPENAI_API_KEY` 環境変数を使用します。このキーは SDK が最初に OpenAI クライアントを作成したときに解決されるため(遅延初期化)、最初のモデル呼び出しの前に環境変数を設定してください。アプリ起動前にその環境変数を設定できない場合は、キーを設定するために [set_default_openai_key()][agents.set_default_openai_key] 関数を使用できます。
デフォルトでは、SDK は LLM リクエストとトレーシングに `OPENAI_API_KEY` 環境変数を使用します。このキーはSDK が初めて OpenAI クライアントを作成するときに解決されます(遅延初期化)。そのため、最初のモデル呼び出しの前に環境変数を設定してください。アプリ起動前にその環境変数を設定できない場合は、[set_default_openai_key()][agents.set_default_openai_key] 関数を使用してキーを設定できます。
```python
from agents import set_default_openai_key
@@ -22,7 +26,7 @@ from agents import set_default_openai_key
set_default_openai_key("sk-...")
```
別の方法として、使用する OpenAI クライアントを設定することもできます。デフォルトでは、 SDK は `AsyncOpenAI` インスタンスを作成し、環境変数の API キーまたは上で設定したデフォルトキーを使用します。これは [set_default_openai_client()][agents.set_default_openai_client] 関数変更できます。
また、使用する OpenAI クライアントを設定することもできます。デフォルトでは、SDK は環境変数の API キーまたは上で設定したデフォルトキーを使用して、`AsyncOpenAI` インスタンスを作成します。これは [set_default_openai_client()][agents.set_default_openai_client] 関数を使用して変更できます。
```python
from openai import AsyncOpenAI
@@ -32,7 +36,14 @@ custom_client = AsyncOpenAI(base_url="...", api_key="...")
set_default_openai_client(custom_client)
```
最後に、使用する OpenAI API をカスタマイズすることもできます。デフォルトでは OpenAI Responses API を使用します。[set_default_openai_api()][agents.set_default_openai_api] 関数を使用すると、これを上書きして Chat Completions API を使用できます。
環境変数ベースのエンドポイント設定を使用したい場合、デフォルトの OpenAI プロバイダーは `OPENAI_BASE_URL` も読み取ります。Responses WebSocket トランスポートを有効にすると、WebSocket の `/responses` エンドポイント用に `OPENAI_WEBSOCKET_BASE_URL` も読み取ります。
```bash
export OPENAI_BASE_URL="https://your-openai-compatible-endpoint.example/v1"
export OPENAI_WEBSOCKET_BASE_URL="wss://your-openai-compatible-endpoint.example/v1"
```
最後に、使用される OpenAI API もカスタマイズできます。デフォルトでは OpenAI Responses API を使用します。[set_default_openai_api()][agents.set_default_openai_api] 関数を使用すると、これを上書きして Chat Completions API を使用できます。
```python
from agents import set_default_openai_api
@@ -40,9 +51,41 @@ from agents import set_default_openai_api
set_default_openai_api("chat_completions")
```
## OpenAI プロバイダーのデフォルト
OpenAI を基盤とするプロバイダーは、モデル名を解決するときにも SDK 全体のデフォルトを読み取ります。OpenAI Responses モデルがデフォルトで WebSocket トランスポートを使用するようにするには、[`set_default_openai_responses_transport()`][agents.set_default_openai_responses_transport] を使用します:
```python
from agents import set_default_openai_responses_transport
set_default_openai_responses_transport("websocket")
```
これは、デフォルトの OpenAI プロバイダーによって解決される OpenAI Responses モデルに影響します。プロバイダーレベルのセットアップ、接続の再利用、キープアライブオプション、カスタム WebSocket エンドポイントについては、[Responses WebSocket トランスポート](models/index.md#responses-websocket-transport) を参照してください。
OpenAI セットアップでプロバイダーレベルのエージェント登録メタデータが必要な場合は、起動時にデフォルトのハーネス ID を一度設定してください:
```python
from agents import set_default_openai_harness
set_default_openai_harness("your-harness-id")
```
完全な登録オブジェクトを渡すこともできます:
```python
from agents import OpenAIAgentRegistrationConfig, set_default_openai_agent_registration
set_default_openai_agent_registration(
OpenAIAgentRegistrationConfig(harness_id="your-harness-id")
)
```
SDK のデフォルトが設定されていない場合、OpenAI を基盤とするプロバイダーは `OPENAI_AGENT_HARNESS_ID` 環境変数にフォールバックします。ハーネス ID が設定されている場合、`agent_harness_id``RunConfig.trace_metadata` にすでに存在する場合を除き、SDK はそれを `agent_harness_id` としてトレースメタデータに追加します。
## トレーシング
トレーシングはデフォルトで有効です。デフォルトでは、上セクションモデルリクエストと同じ OpenAI API キー(つまり環境変数または設定したデフォルトキー)を使用します。トレーシング使用する API キーは、[`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 関数個別に設定できます。
トレーシングはデフォルトで有効です。デフォルトでは、上セクションで説明したモデルリクエストと同じ OpenAI API キー(つまり環境変数または設定したデフォルトキー)を使用します。トレーシング使用する API キーは、[`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 関数を使用して個別に設定できます。
```python
from agents import set_tracing_export_api_key
@@ -50,7 +93,22 @@ from agents import set_tracing_export_api_key
set_tracing_export_api_key("sk-...")
```
デフォルトのエクスポーター使用時にトレースを特定の organization や project に紐付ける必要がある場合は、アプリ起動前に次の環境変数を設定してください
モデルのトラフィックではあるキーまたはクライアントを使用し、トレーシングでは別の OpenAI キーを使用したい場合は、デフォルトのキーまたはクライアントを設定するときに `use_for_tracing=False` を渡し、そのうえでトレーシングを個別に設定してください。カスタムクライアントを使用していない場合は、同じパターンを [`set_default_openai_key()`][agents.set_default_openai_key] にも適用できます
```python
from openai import AsyncOpenAI
from agents import (
set_default_openai_client,
set_tracing_export_api_key,
)
custom_client = AsyncOpenAI(base_url="https://your-openai-compatible-endpoint.example/v1", api_key="provider-key")
set_default_openai_client(custom_client, use_for_tracing=False)
set_tracing_export_api_key("sk-tracing")
```
デフォルトエクスポーターを使用するときに、トレースを特定の組織またはプロジェクトに関連付ける必要がある場合は、アプリの起動前に次の環境変数を設定してください:
```bash
export OPENAI_ORG_ID="org_..."
@@ -77,7 +135,7 @@ from agents import set_tracing_disabled
set_tracing_disabled(True)
```
トレーシング有効のままにしつつ、機密性の高い可能性ある入出力をトレースペイロードから除外したい場合は、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] を `False` に設定してください
トレーシング有効のままにしつつ、機微情報を含む可能性ある入力/出力をトレースペイロードから除外したい場合は、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] を `False` に設定してください:
```python
from agents import Runner, RunConfig
@@ -89,19 +147,19 @@ await Runner.run(
)
```
アプリ起動前にこの環境変数を設定すれば、コードを書かずにデフォルトを変更することもできます。
コードを使わずにデフォルトを変更することもできます。アプリの起動前にこの環境変数を設定してください:
```bash
export OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA=0
```
トレーシング制御の詳細は、[トレーシングガイド](tracing.md) を参照してください。
トレーシング制御の詳細については、[トレーシングガイド](tracing.md) を参照してください。
## デバッグロギン
## デバッグログ
SDK は 2 つの Python ロガー(`openai.agents``openai.agents.tracing`)を定義しており、デフォルトではハンドラーをアタッチしません。ログはアプリケーションの Python ロギング設定に従います。
SDK は 2 つの Python ロガー(`openai.agents``openai.agents.tracing`)を定義しており、デフォルトではハンドラーをアタッチしません。ログはアプリケーションの Python ロギング設定に従います。
詳細なロギングを有効にするには、[`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 関数を使用します。
詳細グを有効にするには、[`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 関数を使用します。
```python
from agents import enable_verbose_stdout_logging
@@ -109,7 +167,7 @@ from agents import enable_verbose_stdout_logging
enable_verbose_stdout_logging()
```
また、ハンドラー、フィルター、フォーマッターなどを追加してログをカスタマイズすることもできます。詳しくは [Python logging guide](https://docs.python.org/3/howto/logging.html) を参照してください。
また、ハンドラー、フィルター、フォーマッターなどを追加してログをカスタマイズすることもできます。詳しくは [Python ロギングガイド](https://docs.python.org/3/howto/logging.html) を参照してください。
```python
import logging
@@ -128,18 +186,18 @@ logger.setLevel(logging.WARNING)
logger.addHandler(logging.StreamHandler())
```
### ログ内の機データ
### ログ内の機データ
一部のログには機密データ(たとえばユーザーデータ)が含まれる可能性があります。
一部のログには、機微データ(たとえばユーザーデータ)が含まれる場合があります。
デフォルトでは、 SDK は LLM の入出力やツールの入出力を **ログに記録しません** 。これらの保護は次によって制御されます
デフォルトでは、SDK は LLM の入力/出力やツールの入力/出力を **ログに記録しません** 。これらの保護は次の項目で制御されます:
```bash
OPENAI_AGENTS_DONT_LOG_MODEL_DATA=1
OPENAI_AGENTS_DONT_LOG_TOOL_DATA=1
```
デバッグのために一時的にこのデータを含める必要がある場合は、アプリ起動前にいずれかの変数を `0`(または `false`)に設定してください
デバッグのためにこのデータを一時的に含める必要がある場合は、アプリ起動前にいずれかの変数を `0`(または `false`)に設定してください:
```bash
export OPENAI_AGENTS_DONT_LOG_MODEL_DATA=0
+42 -40
View File
@@ -4,47 +4,49 @@ search:
---
# コンテキスト管理
コンテキストは多義的な用語です。主に重要になるコンテキストは 2 つあります
コンテキストは多義的な用語です。考慮すべきコンテキストには、主に 2 つの種類があります:
1. コード内でローカルに利用可能なコンテキスト: これは、ツール関数の実行時、`on_handoff` のようなコールバック、ライフサイクルフック内などで必要になる可能性あるデータや依存関係です。
2. LLM 利用可能なコンテキスト: これは、レスポンス生成時に LLM が参照するデータです。
1. コードからローカルに利用できるコンテキスト: これは、ツール関数の実行時、`on_handoff` のようなコールバック、ライフサイクルフック内などで必要になる可能性あるデータや依存関係です。
2. LLM 利用できるコンテキスト: これは、LLM が応答を生成するときに参照するデータです。
## ローカルコンテキスト
これは [`RunContextWrapper`][agents.run_context.RunContextWrapper] クラス、その中の [`context`][agents.run_context.RunContextWrapper.context] プロパティで表現されます。仕組みは次のとおりです
これは [`RunContextWrapper`][agents.run_context.RunContextWrapper] クラス、およびその中の [`context`][agents.run_context.RunContextWrapper.context] プロパティで表現されます。仕組みは次のとおりです:
1. 任意の Python オブジェクトを作成します。一般的なパターンは dataclass または Pydantic オブジェクトを使ことです。
2. そのオブジェクトを各種 run メソッドに渡します (例: `Runner.run(..., context=whatever)`)。
3. すべてのツール呼び出し、ライフサイクルフックなどに`RunContextWrapper[T]` というラッパーオブジェクトが渡されます。ここで `T` はコンテキストオブジェクトの型であり`wrapper.context` アクセスできます。
1. 任意の Python オブジェクトを作成します。一般的なパターンは dataclass Pydantic オブジェクトを使用することです。
2. そのオブジェクトを各種実行メソッドに渡します (例: `Runner.run(..., context=whatever)`)。
3. すべてのツール呼び出し、ライフサイクルフックなどには、ラッパーオブジェクト `RunContextWrapper[T]` が渡されます。ここで `T` はコンテキストオブジェクトの型を表し`wrapper.context` を通じてアクセスできます。
注意すべき **最も重要な** 点: 特定のエージェント実行におけるすべてのエージェント、ツール関数、ライフサイクルなどは、同じコンテキストの __ を使用する必要があります。
一部のランタイム固有のコールバックでは、SDK はより特殊化された `RunContextWrapper[T]` のサブクラスを渡す場合があります。たとえば、関数ツールのライフサイクルフックは通常 `ToolContext` を受け取り、これは `tool_call_id``tool_name``tool_arguments` などのツール呼び出しメタデータも公開します。
コンテキストは次のような用途で使えます。
認識すべき **最も重要な** 点は、あるエージェント実行におけるすべてのエージェント、ツール関数、ライフサイクルなどが、同じ __ のコンテキストを使用しなければならないということです。
- 実行時の文脈データ (例: ユーザー名 / uid やその他のユーザー情報)
- 依存関係 (例: logger オブジェクト、データフェッチャーなど)
コンテキストは、たとえば次の用途に使用できます:
- 実行時のコンテキストデータ (例: ユーザー名 / uid や、ユーザーに関するその他の情報)
- 依存関係 (例: ロガーオブジェクト、データ取得器など)
- ヘルパー関数
!!! danger "注記"
コンテキストオブジェクトは LLM に送信され **ません**。これは純粋にローカルオブジェクトであり、読み取り、書き込み、メソッド呼び出しを行えます。
コンテキストオブジェクトは LLM に **送信されません**。これは完全にローカルオブジェクトであり、読み取り、書き込み、メソッド呼び出しができます。
単一の実行内では、派生ラッパーは同じ基盤の app コンテキスト、承認状態、使用量トラッキングを共有します。ネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行では別の `tool_input` が付与される場合がありますが、既定では app 状態の分離コピーは取得しません。
1 回の実行内では、派生したラッパーは同じ基盤となるアプリコンテキスト、承認状態、使用状況の追跡を共有します。ネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行では異なる `tool_input` を付加する場合がありますが、デフォルトではアプリ状態の分離コピーは取得しません。
### `RunContextWrapper` の公開内容
[`RunContextWrapper`][agents.run_context.RunContextWrapper] は、app で定義したコンテキストオブジェクトラッパーです。実際には、主に次を使用します
[`RunContextWrapper`][agents.run_context.RunContextWrapper] は、アプリで定義したコンテキストオブジェクトを包むラッパーです。実際には、ほとんどの場合、次のものを使用します:
- 独自の可変 app 状態および依存関係には [`wrapper.context`][agents.run_context.RunContextWrapper.context]。
- 現在の実行全体で集計されたリクエストおよびトークン使用量には [`wrapper.usage`][agents.run_context.RunContextWrapper.usage]。
- 現在の実行が [`Agent.as_tool()`][agents.agent.Agent.as_tool] 内で動作している場合の構造化入力には [`wrapper.tool_input`][agents.run_context.RunContextWrapper.tool_input]。
- 承認状態をプログラムから更新する必要がある場合は [`wrapper.approve_tool(...)`][agents.run_context.RunContextWrapper.approve_tool] / [`wrapper.reject_tool(...)`][agents.run_context.RunContextWrapper.reject_tool]。
- [`wrapper.context`][agents.run_context.RunContextWrapper.context]: 独自の可変なアプリ状態と依存関係に使用します
- [`wrapper.usage`][agents.run_context.RunContextWrapper.usage]: 現在の実行全体で集計されたリクエストおよびトークン使用量に使用します
- [`wrapper.tool_input`][agents.run_context.RunContextWrapper.tool_input]: 現在の実行が [`Agent.as_tool()`][agents.agent.Agent.as_tool] の内部で実行されている場合の構造化入力に使用します
- [`wrapper.approve_tool(...)`][agents.run_context.RunContextWrapper.approve_tool] / [`wrapper.reject_tool(...)`][agents.run_context.RunContextWrapper.reject_tool]: 承認状態をプログラムで更新する必要がある場合に使用します
`wrapper.context` のみが app で定義したオブジェクトです。その他のフィールドは SDK が管理する実行時メタデータです。
アプリで定義したオブジェクトは `wrapper.context` のみです。その他のフィールドは SDK が管理するランタイムメタデータです。
後で human-in-the-loop や永続ジョブワークフローのために [`RunState`][agents.run_state.RunState] をシリアライズする場合、その実行時メタデータは状態とともに保存されます。シリアライズた状態を永続化または送信する予定がある場合、[`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] に秘密情報を入れるのは避けてください。
後で human-in-the-loop や耐久ジョブワークフローのために [`RunState`][agents.run_state.RunState] をシリアライズする場合、そのランタイムメタデータは状態とともに保存されます。シリアライズされた状態を永続化または送信する予定がある場合、[`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] にシークレットを入れないでください。
会話状態は別の関心事です。ターンをどのように引き継ぐかに応じて、`result.to_input_list()``session``conversation_id`、または `previous_response_id` を使用してください。の判断については [results](results.md)、[running agents](running_agents.md)、[sessions](sessions/index.md) を参照してください。
会話状態は別の関心事です。ターンをどのように引き継ぐかに応じて、`result.to_input_list()``session``conversation_id`、または `previous_response_id` を使用してください。の判断については、[実行結果](results.md)、[エージェントの実行](running_agents.md)、[セッション](sessions/index.md) を参照してください。
```python
import asyncio
@@ -83,18 +85,18 @@ if __name__ == "__main__":
asyncio.run(main())
```
1. これがコンテキストオブジェクトです。ここでは dataclass を使ていますが、任意の型を使用できます。
2. これツールです。`RunContextWrapper[UserInfo]` を受け取ることがわかります。ツール実装はコンテキスト読み取ります。
3. エージェントにジェネリック `UserInfo` を指定しているため、型チェッカーがエラーを検出できます (たとえば、異なるコンテキスト型を受け取るツールを渡そうとした場合)。
1. これがコンテキストオブジェクトです。ここでは dataclass を使用していますが、任意の型を使用できます。
2. これツールです。`RunContextWrapper[UserInfo]` を受け取っていることがわかります。ツール実装はコンテキストから読み取ります。
3. 型チェッカーがエラーを検出できるように、エージェントにジェネリック `UserInfo` を指定します (たとえば、異なるコンテキスト型を受け取るツールを渡そうとした場合)。
4. コンテキストは `run` 関数に渡されます。
5. エージェントは正しくツールを呼び出し、年齢を取得します。
---
### 高度な利用: `ToolContext`
### 高度な内容: `ToolContext`
場合によっては、実行中のツールに関する追加メタデータ (名前、呼び出し ID、raw 引数文字列など) にアクセスしたいことがあります。
このために`RunContextWrapper` を拡張した [`ToolContext`][agents.tool_context.ToolContext] クラスを使用できます。
場合によっては、実行中のツールに関する追加メタデータ (名前、呼び出し ID、生の引数文字列など) にアクセスしたいことがあります。
この場合`RunContextWrapper` を拡張する [`ToolContext`][agents.tool_context.ToolContext] クラスを使用できます。
```python
from typing import Annotated
@@ -123,24 +125,24 @@ agent = Agent(
```
`ToolContext``RunContextWrapper` と同じ `.context` プロパティを提供し、
さらに現在のツール呼び出しに固有の追加フィールド提供します
現在のツール呼び出しに固有の追加フィールド提供します:
- `tool_name` 呼び出されるツール
- `tool_call_id` – このツール呼び出しの一意識別子
- `tool_arguments` ツールに渡される raw 引数字符串
- `tool_namespace` ツールが `tool_namespace()` またはの名前空間付きサーフェス経由で読み込まれた場合の、ツール呼び出し Responses 名前空間
- `qualified_tool_name` 名前空間が利用可能な場合の、名前空間付きツール名
- `tool_name` 呼び出されているツールの名前
- `tool_call_id` このツール呼び出しの一意識別子
- `tool_arguments` ツールに渡された生の引数文字列
- `tool_namespace` ツールが `tool_namespace()` またはの名前空間付きサーフェスを通じて読み込まれた場合の、ツール呼び出しに対する Responses 名前空間
- `qualified_tool_name` 名前空間が利用できる場合に、その名前空間で修飾されたツール名
実行中にツールレベルのメタデータが必要な場合は `ToolContext` を使用してください。
エージェントとツール間で一般的なコンテキスト共有は、`RunContextWrapper` で十分です。`ToolContext``RunContextWrapper` を拡張しているため、ネストされた `Agent.as_tool()` 実行構造化入力が渡された場合は `.tool_input` も公開できます。
実行中にツールレベルのメタデータが必要な場合は`ToolContext` を使用してください。
エージェントとツール間で一般的なコンテキスト共有を行うには、`RunContextWrapper` のままで十分です。`ToolContext``RunContextWrapper` を拡張しているため、ネストされた `Agent.as_tool()` 実行構造化入力を提供した場合`.tool_input` も公開できます。
---
## エージェント / LLM コンテキスト
LLM が呼び出されるとき、参照できるデータは会話履歴内のもの **の** です。これは、LLM に新しいデータを利用可能にしたい場合、それを会話履歴内で利用可能にする方法で渡す必要があることを意味します。方法はいくつかあります
LLM が呼び出されるとき、その LLM が参照できる **唯一** データは会話履歴に含まれるものです。つまり、新しいデータを LLM に利用可能にしたい場合、そ履歴内で利用可能になるような方法で行う必要があります。これにはいくつかの方法があります:
1. Agent `instructions` に追加できます。これは「システムプロンプト」または「開発者メッセージ」とも呼ばれます。システムプロンプトは静的文字列にも、コンテキストを受け取って文字列を返す動的関数にもできます。これは、常に有用な情報 (たとえばユーザーや現在日付) に対する一般的な手法です。
2. `Runner.run` 関数を呼び出すとき `input` に追加します。これは `instructions` の手法に似ていますが、[chain of command](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command) より下位のメッセージを持てます。
3. 関数ツールを通じて公開します。これは _オンデマンド_ のコンテキストに有用です。つまり、LLM がデータを必要とするタイミングを判断し、そのデータ取得ためにツールを呼び出せます。
4. retrieval または Web 検索を使用します。これらは、ファイルやデータベース (retrieval)、または Web (Web 検索) から関連データを取得できる特なツールです。これは、関連する文脈データに基づいてレスポンスを「グラウンディング」するのに有用です。
1. エージェント`instructions` に追加できます。これは「システムプロンプト」または「開発者メッセージ」とも呼ばれます。システムプロンプトは静的文字列にも、コンテキストを受け取って文字列を出力する動的関数にもできます。これは、常に役立つ情報 (たとえばユーザーの名前や現在日付) に対する一般的な手法です。
2. `Runner.run` 関数を呼び出すとき `input` に追加します。これは `instructions` の手法に似ていますが、[指揮系統](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command) においてより下位のメッセージにできます。
3. 関数ツールを介して公開します。これは _オンデマンド_ のコンテキストに便利です。LLM がデータを必要とするタイミングを判断し、そのデータ取得するためにツールを呼び出せます。
4. リトリーバルまたは Web 検索を使用します。これらは、ファイルやデータベースから関連データを取得する (リトリーバル)、または Web から取得する (Web 検索) ことができる特なツールです。これは、関連するコンテキストデータに基づいて応答を「グラウンディング」するのに便利です。
+85 -56
View File
@@ -4,104 +4,133 @@ search:
---
# コード例
[repo](https://github.com/openai/openai-agents-python/tree/main/examples) の examples セクションで、 SDK のさまざまなサンプル実装をご確認ください。examples は、異なるパターンと機能を示す複数のカテゴリーに整理されています。
[リポジトリ](https://github.com/openai/openai-agents-python/tree/main/examples) のコード例セクションで、SDK のさまざまな実装サンプルをご覧ください。コード例は複数のカテゴリーに整理され、それぞれ異なるパターンと機能を示します。
## カテゴリー
- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):**
このカテゴリーのコード例では、一般的なエージェント設計パターンを示しています。たとえば次のとおりです。
- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** このカテゴリーのコード例では、次のような一般的なエージェント設計パターンを示します。
- 決定論的ワークフロー
- Agents as tools
- ストリーミングイベントを使用する Agents as tools (`examples/agent_patterns/agents_as_tools_streaming.py`)
- 構造化入力パラメーターを使用する Agents as tools (`examples/agent_patterns/agents_as_tools_structured.py`)
- エージェントの並列実行
- 条件付きツール使用
- 条件付きツール使用
- 異なる動作でのツール使用の強制 (`examples/agent_patterns/forcing_tool_use.py`)
- 入出力ガードレール
- 判としての LLM
-定役としての LLM
- ルーティング
- ストリーミングガードレール
- ツール承認と状態のシリアル化を伴う人間参加型フロー (`examples/agent_patterns/human_in_the_loop.py`)
- ストリーミングを伴う人間参加型フロー (`examples/agent_patterns/human_in_the_loop_stream.py`)
- 承認フロー向けのカスタム拒否メッセージ (`examples/agent_patterns/human_in_the_loop_custom_rejection.py`)
- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):**
これらのコード例では、 SDK の基本的な機能を紹介しています。たとえば次のとおりです。
- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** これらのコード例では、次のような SDK の基本機能を紹介します。
- Hello World のコード例 (デフォルトモデル、 GPT-5、オープンウェイトモデル)
- エージェントライフサイクル管理
- Hello world のコード例デフォルトモデル、GPT-5、オープンウェイトモデル
- エージェントライフサイクル管理
- 実行フックとエージェントフックのライフサイクルのコード例 (`examples/basic/lifecycle_example.py`)
- 動的システムプロンプト
- ストリーミング出力 (テキスト、項目、関数呼び出し引数)
- ターン間で共有セッションヘルパーを使用する Responses websocket transport (`examples/basic/stream_ws.py`)
- 基本的なツールの使用 (`examples/basic/tools.py`)
- ツールの入出力ガードレール (`examples/basic/tool_guardrails.py`)
- 画像形式のツール出力 (`examples/basic/image_tool_output.py`)
- ストリーミング出力(テキスト、アイテム、関数呼び出しの引数)
- ターン間で共有されるセッションヘルパーを使用する Responses WebSocket トランスポート (`examples/basic/stream_ws.py`)
- プロンプトテンプレート
- ファイル処理 (ローカルおよびリモート、画像および PDF)
- 使用状況トラッキング
- Runner 管理再試行設定 (`examples/basic/retry.py`)
- LiteLLM を使用した Runner 管理再試行 (`examples/basic/retry_litellm.py`)
- 非 strict な出力型
- ファイル処理ローカルおよびリモート、画像および PDF
- 使用量の追跡
- Runner 管理する再試行設定 (`examples/basic/retry.py`)
- サードパーティー製アダプターを介して Runner 管理する再試行 (`examples/basic/retry_litellm.py`)
- 厳密でない出力型
- 以前のレスポンス ID の使用
- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):**
航空会社向けのカスタマーサービスシステムのコード例です。
- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** 航空会社向けカスタマーサービスシステムのコード例です。
- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):**
金融データ分析向けに、エージェントとツールを使った構造化リサーチワークフローを示す金融リサーチエージェントです。
- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** エージェントとツールを使用した、金融データ分析向けの構造化された調査ワークフローを示す金融調査エージェントです。
- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):**
メッセージフィルタリングを使ったエージェントハンドオフの実践的なコード例をご覧ください。
- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** メッセージフィルタリングを伴うエージェントのハンドオフの実践的なコード例です。以下が含まれます。
- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):**
ホストされた MCP (Model context protocol) コネクタと承認の使い方を示すコード例です。
- メッセージフィルターのコード例 (`examples/handoffs/message_filter.py`)
- ストリーミングを伴うメッセージフィルター (`examples/handoffs/message_filter_streaming.py`)
- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):**
MCP (Model context protocol) を使ってエージェントを構築する方法を学べます。内容は次のとおりです。
- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** OpenAI Responses API でホスト型 MCP (Model Context Protocol) を使用する方法を示すコード例です。以下が含まれます。
- 承認不要のシンプルなホスト型 MCP (`examples/hosted_mcp/simple.py`)
- Google Calendar などの MCP コネクター (`examples/hosted_mcp/connectors.py`)
- 中断ベースの承認を使用する人間参加型フロー (`examples/hosted_mcp/human_in_the_loop.py`)
- MCP ツール呼び出しの承認時コールバック (`examples/hosted_mcp/on_approval.py`)
- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** MCP (Model Context Protocol) を使用してエージェントを構築する方法を学びます。以下が含まれます。
- ファイルシステムのコード例
- Git のコード例
- MCP プロンプトサーバーのコード例
- SSE (Server-Sent Events) のコード例
- ストリーム可能な HTTP のコード例
- SSE リモートサーバー接続 (`examples/mcp/sse_remote_example`)
- Streamable HTTP のコード例
- Streamable HTTP リモート接続 (`examples/mcp/streamable_http_remote_example`)
- Streamable HTTP 向けのカスタム HTTP クライアントファクトリー (`examples/mcp/streamablehttp_custom_client_example`)
- `MCPUtil.get_all_function_tools` を使用したすべての MCP ツールの事前取得 (`examples/mcp/get_all_mcp_tools_example`)
- FastAPI と組み合わせた MCPServerManager (`examples/mcp/manager_example`)
- MCP ツールのフィルタリング (`examples/mcp/tool_filter_example`)
- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):**
エージェント向けのさまざまなメモリ実装のコード例です。内容は次のとおりです。
- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** エージェント向けのさまざまなメモリ実装のコード例です。以下が含まれます。
- SQLite セッションストレージ
- 高度な SQLite セッションストレージ
- Redis セッションストレージ
- SQLAlchemy セッションストレージ
- Dapr state store セッションストレージ
- 暗号化セッションストレージ
- Dapr ステートストアのセッションストレージ
- 暗号化されたセッションストレージ
- OpenAI Conversations セッションストレージ
- Responses compaction セッションストレージ
- `ModelSettings(store=False)` を使たステートレスな Responses compaction (`examples/memory/compaction_session_stateless_example.py`)
- Responses 圧縮セッションストレージ
- `ModelSettings(store=False)` を使用したステートレスな Responses 圧縮 (`examples/memory/compaction_session_stateless_example.py`)
- ファイルベースのセッションストレージ (`examples/memory/file_session.py`)
- 人間参加型フローを伴うファイルベースのセッション (`examples/memory/file_hitl_example.py`)
- 人間参加型フローを伴う SQLite インメモリセッション (`examples/memory/memory_session_hitl_example.py`)
- 人間参加型フローを伴う OpenAI Conversations セッション (`examples/memory/openai_session_hitl_example.py`)
- セッションをまたぐ HITL の承認/拒否シナリオ (`examples/memory/hitl_session_scenario.py`)
- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):**
カスタムプロバイダーや LiteLLM 統合を含め、 SDK で非 OpenAI モデルを使う方法を確認できます。
- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** カスタムプロバイダーやサードパーティー製アダプターなど、OpenAI 以外のモデルを SDK で使用する方法を紹介します。
- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):**
SDK を使用してリアルタイム体験を構築する方法を示すコード例です。内容は次のとおりです。
- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** SDK を使用してリアルタイム体験を構築する方法を示すコード例です。以下が含まれます。
- 構造化テキストと画像メッセージを使 Web アプリケーションパターン
- コマンドライン音声ループと再生処理
- WebSocket 経由の Twilio Media Streams 統合
- Realtime Calls API のアタッチフローを使 Twilio SIP 統合
- 構造化されたテキストメッセージと画像メッセージを使用する Web アプリケーションパターン
- コマンドラインでの音声ループと再生処理
- WebSocket を介した Twilio Media Streams 統合
- Realtime Calls API のアタッチフローを使用した Twilio SIP 統合
- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):**
reasoning content と structured outputs の扱い方を示すコード例です。
- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** 推論コンテンツの扱い方を示すコード例です。以下が含まれます。
- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):**
複雑なマルチエージェントのリサーチワークフローを示す、シンプルなディープリサーチクローンです。
- Runner API を使用した推論コンテンツ、ストリーミングおよび非ストリーミング (`examples/reasoning_content/runner_example.py`)
- OpenRouter 経由の OSS モデルを使用した推論コンテンツ (`examples/reasoning_content/gpt_oss_stream.py`)
- 基本的な推論コンテンツのコード例 (`examples/reasoning_content/main.py`)
- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):**
次のような OpenAI がホストするツールと実験的な Codex ツール機能の実装方法を学べます。
- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** 複雑なマルチエージェント調査ワークフローを示す、シンプルなディープリサーチのクローンです。
- Web 検索 とフィルター付き Web 検索
- **[sandbox](https://github.com/openai/openai-agents-python/tree/main/examples/sandbox):** 分離されたワークスペースでエージェントを実行するためのコード例です。以下が含まれます。
- 基本的なサンドボックスエージェントのセットアップ (`examples/sandbox/basic.py`)
- Unix ローカルおよび Docker サンドボックスのライフサイクルのコード例
- サンドボックスを利用したハンドオフ (`examples/sandbox/handoffs.py`)
- サンドボックスのメモリとスナップショットからの再開 (`examples/sandbox/memory.py`)
- ツールとして公開されるサンドボックスエージェント (`examples/sandbox/sandbox_agents_as_tools.py`)
- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** OpenAI がホストするツールや実験的な Codex ツール機能の実装方法を学びます。以下が含まれます。
- Web 検索、およびフィルター付き Web 検索
- ファイル検索
- Code Interpreter
- インラインスキル付きホストコンテナーシェル (`examples/tools/container_shell_inline_skill.py`)
- スキル参照付きホストコンテナーシェル (`examples/tools/container_shell_skill_reference.py`)
- ローカルスキル付きローカルシェル (`examples/tools/local_shell_skill.py`)
- 名前空間と遅延ツールを使ったツール検索 (`examples/tools/tool_search.py`)
- Code interpreter
- ファイル編集と承認を伴うパッチ適用ツール (`examples/tools/apply_patch.py`)
- 承認コールバックを伴うシェルツールの実行 (`examples/tools/shell.py`)
- 中断ベースの人間参加型承認を伴うシェルツール (`examples/tools/shell_human_in_the_loop.py`)
- インラインスキルを備えたホスト型コンテナシェル (`examples/tools/container_shell_inline_skill.py`)
- スキル参照を備えたホスト型コンテナシェル (`examples/tools/container_shell_skill_reference.py`)
- ローカルスキルを備えたローカルシェル (`examples/tools/local_shell_skill.py`)
- 名前空間と遅延ツールを使用したツール検索 (`examples/tools/tool_search.py`)
- コンピュータ操作
- 画像生成
- 実験的な Codex ツールワークフロー (`examples/tools/codex.py`)
- 実験的な Codex 同一スレッドワークフロー (`examples/tools/codex_same_thread.py`)
- 実験的な Codex 同一スレッドワークフロー (`examples/tools/codex_same_thread.py`)
- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):**
ストリーミング音声のコード例を含む、 TTS および STT モデルを使用した音声エージェントのコード例をご覧ください。
- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** TTS および STT モデルを使用した音声エージェントのコード例をご覧ください。ストリーミング音声のコード例も含まれます。
+43 -42
View File
@@ -4,74 +4,75 @@ search:
---
# ガードレール
ガードレールを使と、ユーザー入力とエージェント出力のチェック検証を行えます。たとえば、顧客リクエスト対応のために非常に高性能(したがって低速 / 高コストなモデルを使エージェントがあるとします。悪意のあるユーザーに、そのモデル数学の宿題を手伝わせたくはありません。そのため、高速 / 低コストなモデルでガードレールを実行できます。ガードレールが悪意のある用を検した場合、すぐにエラーを発生させて高コストなモデルの実行を防げます。これにより時間とコストを節約できます( **blocking guardrails** を使う場合。並列ガードレールでは、ガードレール完了前に高コストなモデルがすでに実行を開始している可能性があります。詳細は下記の「実行モード」を参照してください)。
ガードレールを使用すると、ユーザー入力とエージェント出力のチェックおよび検証を行えます。たとえば、顧客からのリクエストを支援するために非常に賢い(そのため低速で高コストなモデルを使用するエージェントがあるとします。悪意のあるユーザーに、そのモデル数学の宿題を手伝わせたくはないはずです。そこで、高速 / 低コストなモデルでガードレールを実行できます。ガードレールが悪意のある使用を検した場合、即座にエラーを送出して高価なモデルの実行を防ぎ、時間と費用を節約できます( **ブロッキングガードレールを使用する場合に限ります。並列ガードレールでは、ガードレール完了する前に、高価なモデルがすでに実行を開始している可能性があります。詳細は下記の「実行モード」を参照してください** )。
ガードレールには 2 種類あります。
1. Input ガードレールは最初のユーザー入力実行されます
2. Output ガードレールは最終的なエージェント出力実行されます
1. 入力ガードレールは最初のユーザー入力に対して実行されます
2. 出力ガードレールは最終的なエージェント出力に対して実行されます
## ワークフロー境界
## ワークフロー境界
ガードレールはエージェントとツールにアタッチされますが、ワークフロー内の同じタイミングで実行されるわけではありません。
ガードレールはエージェントとツールにアタッチされますが、すべてがワークフロー内の同じ時点で実行されるわけではありません。
- **Input ガードレール** はチェーン内の最初のエージェントに対してのみ実行されます。
- **Output ガードレール** は最終出力を生成するエージェントに対してのみ実行されます。
- **ツールガードレール** はカスタム関数ツール呼び出しごとに実行され、Input ガードレール実行前、Output ガードレールは実行後に実行されます。
- **入力ガードレール**チェーン内の最初のエージェントに対してのみ実行されます。
- **出力ガードレール**最終出力を生成するエージェントに対してのみ実行されます。
- **ツールガードレール**、すべてのカスタム関数ツール呼び出し実行され、実行前に入力ガードレール実行後に出力ガードレール実行されます。
manager、ハンドオフ、または委譲された specialist を含むワークフローで、カスタム関数ツール呼び出しごとにチェックが必要な場合は、エージェントレベルの Input / Output ガードレールのみに頼るのではなく、ツールガードレールを使用してください。
マネージャー、ハンドオフ、または委任先の専門家を含むワークフローで、カスタム関数ツール呼び出しの前後にチェックが必要な場合は、エージェントレベルの入力 / 出力ガードレールだけに頼るのではなく、ツールガードレールを使用してください。
## Input ガードレール
## 入力ガードレール
Input ガードレールは 3 ステップで実行されます。
入力ガードレールは 3 ステップで実行されます。
1. まず、ガードレールはエージェントに渡されたものと同じ入力を受け取ります。
2. 次に、ガードレール関数が実行され [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] 生成し、それが [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult] にラップされます
3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合 [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 例外が発生するため、ユーザーへの適切応答例外処理を行えます。
2. 次に、ガードレール関数が実行され [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] 生成されます。これはその後 [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult] にラップされます
3. 最後に、 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合 [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 例外が送出されるため、ユーザー適切応答したり、例外処理したりできます。
!!! Note
Input ガードレールはユーザー入力に対して実行ることを想定しているため、エージェントのガードレールはそのエージェントが *最初* エージェントである場合にのみ実行されます。`guardrails` プロパティが `Runner.run` に渡されるのではなくエージェントにある理由は何か、と疑問に思うかもしれません。これは、ガードレールが実際の Agent に関連することが多く、エージェントごとに異なるガードレールを実行するため、コードを同じ場所に置くことで可読性が向上するためです。
入力ガードレールはユーザー入力に対して実行されることを想定しているため、エージェントのガードレールはそのエージェントが *最初* エージェントである場合にのみ実行されます。なぜ `guardrails` プロパティが `Runner.run` に渡されるのではなくエージェントにあるのか疑問に思うかもしれません。これは、ガードレールが実際のエージェントに関連していることが多いためです。エージェントごとに異なるガードレールを実行するため、コードを同じ場所に配置しておくと可読性の面で役立ちます。
### 実行モード
Input ガードレールは 2 つの実行モードをサポートしています。
入力ガードレールは 2 つの実行モードをサポートします。
- **並列実行**(デフォルト、`run_in_parallel=True`: ガードレールはエージェント実行と同時に並行して実行されます。両方が同時に開始されるため、レイテンシの面で最も有利です。ただし、ガードレールが失敗した場合、キャンセルされる前にエージェントがすでにトークンを消費し、ツールを実行している可能性があります。
- **並列実行** (デフォルト、 `run_in_parallel=True` : ガードレールはエージェント実行と並行して実行されます。両方が同時に開始されるため、レイテンシが最も良くなります。ただし、ガードレールが失敗した場合、キャンセルされる前にエージェントがすでにトークンを消費し、ツールを実行している可能性があります。
- **ブロッキング実行**`run_in_parallel=False`: ガードレールはエージェント開始 ** 実行され、完了します。ガードレールの tripwire がトリガーされた場合、エージェントは実行されないため、トークン消費とツール実行を防げます。これはコスト最適化に理想的で、ツール呼び出しによる潜在的な副作用を避けたい場合にも適しています。
- **ブロッキング実行** `run_in_parallel=False` : ガードレールはエージェント開始する ** 実行され、完了します。ガードレールのトリップワイヤーが発火した場合、エージェントは一切実行されないため、トークン消費とツール実行を防げます。これはコスト最適化、ツール呼び出しによる潜在的な副作用を避けたい場合に最適です。
## Output ガードレール
## 出力ガードレール
Output ガードレールは 3 ステップで実行されます。
出力ガードレールは 3 ステップで実行されます。
1. まず、ガードレールはエージェントが生成した出力を受け取ります。
2. 次に、ガードレール関数が実行され [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] 生成し、それが [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] にラップされます
3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合 [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 例外が発生するため、ユーザーへの適切応答例外処理を行えます。
1. まず、ガードレールはエージェントによって生成された出力を受け取ります。
2. 次に、ガードレール関数が実行され [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] 生成されます。これはその後 [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] にラップされます
3. 最後に、 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合 [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 例外が送出されるため、ユーザー適切応答したり、例外処理したりできます。
!!! Note
Output ガードレールは最終的なエージェント出力に対して実行ることを想定しているため、エージェントのガードレールはそのエージェントが *最後* エージェントである場合にのみ実行されます。Input ガードレールと同様に、これはガードレールが実際の Agent に関連することが多く、エージェントごとに異なるガードレールを実行するため、コードを同じ場所に置くことで可読性が向上するためです。
出力ガードレールは最終的なエージェント出力に対して実行されることを想定しているため、エージェントのガードレールはそのエージェントが *最後* エージェントである場合にのみ実行されます。入力ガードレールと同様に、これはガードレールが実際のエージェントに関連していることが多いためです。エージェントごとに異なるガードレールを実行するため、コードを同じ場所に配置しておくと可読性の面で役立ちます。
Output ガードレールは常にエージェント完了後に実行されるため、`run_in_parallel` パラメーターはサポートしていません。
出力ガードレールは必ずエージェント完了後に実行されるため、 `run_in_parallel` パラメーターはサポートしません。
## ツールガードレール
ツールガードレールは **function tools** をラップし、実行の前後でツール呼び出しを検証またはブロックできます。設定はツール自体に対して行い、そのツールが呼び出されるたびに実行されます。
ツールガードレールは **関数ツール** をラップし、実行の前後でツール呼び出しを検証またはブロックできるようにします。これはツール自体に設定され、そのツールが呼び出されるたびに実行されます。
- Input ツールガードレールはツール実行前に実行され、呼び出しをスキップする、メッセージで出力を置き換える、または tripwire を発生させることができます。
- Output ツールガードレールはツール実行後に実行され、出力を置き換えるか、tripwire を発生させることができます。
- ツールガードレールは [`function_tool`][agents.tool.function_tool] で作成された関数ツールにのみ適用されます。ハンドオフは通常の関数ツールパイプラインではなく SDK のハンドオフパイプラインを通るため、ツールガードレールはハンドオフ呼び出し自体には適用されません。Hosted ツール(`WebSearchTool``FileSearchTool``HostedMCPTool``CodeInterpreterTool``ImageGenerationTool`)および組み込み実行ツール(`ComputerTool``ShellTool``ApplyPatchTool``LocalShellTool`)もこのガードレールパイプラインを使用せず、[`Agent.as_tool()`][agents.agent.Agent.as_tool] でも現在はツールガードレールオプションを直接公開していません
- 入力ツールガードレールはツール実行前に実行され、呼び出しをスキップしたり、出力をメッセージに置き換えたり、トリップワイヤーを送出したりできます。
- 出力ツールガードレールはツール実行後に実行され、出力を置き換えたり、トリップワイヤーを送出したりできます。
- 関数ツールに承認が必要な場合、入力ツールガードレールは通常、承認後かつ実行直前に実行されます。保留中の承認割り込みが発行される前にこれらの入力チェックを実行したい場合は、 [`RunConfig.tool_execution`][agents.run.RunConfig.tool_execution] を [`ToolExecutionConfig(pre_approval_tool_input_guardrails=True)`][agents.run.ToolExecutionConfig] に設定してください。この承認前チェックに合格した呼び出しも、ツールが実行される前に、承認後に再度チェックされます
- ツールガードレールは、 [`function_tool`][agents.tool.function_tool] で作成された関数ツールにのみ適用されます。ハンドオフは通常の関数ツールパイプラインではなく、 SDK のハンドオフパイプラインを通じて実行されるため、ツールガードレールはハンドオフ呼び出し自体には適用されません。ホスト型ツール( `WebSearchTool``FileSearchTool``HostedMCPTool``CodeInterpreterTool``ImageGenerationTool` )と組み込み実行ツール( `ComputerTool``ShellTool``ApplyPatchTool``LocalShellTool` )もこのガードレールパイプラインを使用しません。また、 [`Agent.as_tool()`][agents.agent.Agent.as_tool] は現在、ツールガードレールのオプションを直接公開していません。
詳細は以下のコードスニペットを参照してください。
詳細は、下記のコードスニペットを参照してください。
## トリップワイヤー
入力または出力がガードレールに失敗した場合、Guardrail は tripwire でこれを通知できます。tripwire がトリガーされたガードレールを検知すると、直ち`{Input,Output}GuardrailTripwireTriggered` 例外を発生させ、Agent の実行を停止します。
入力または出力がガードレールに合格しなかった場合、ガードレールはトリップワイヤーでこれを知らせることができます。トリップワイヤーが発火したガードレールを検出した時点で、即座`{Input,Output}GuardrailTripwireTriggered` 例外を送出し、エージェントの実行を停止します。
## ガードレール実装
## ガードレール実装
入力を受け取り、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を返す関数を提供する必要があります。この例では、内部で Agent を実行してこれを実現します。
入力を受け取り、 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を返す関数を用意する必要があります。この例では、内部でエージェントを実行することでこれを行います。
```python
from pydantic import BaseModel
@@ -124,12 +125,12 @@ async def main():
print("Math homework guardrail tripped")
```
1. このエージェントをガードレール関数で使用します。
2. これはエージェントの入力 / コンテキストを受け取り、結果を返すガードレール関数です。
3. ガードレール結果に追加情報を含められます。
4. これはワークフローを定義する実際のエージェントです。
1. このエージェントをガードレール関数で使用します。
2. これはエージェントの入力 / コンテキストを受け取り、実行結果を返すガードレール関数です。
3. ガードレールの実行結果に追加情報を含めることができます。
4. これはワークフローを定義する実際のエージェントです。
Output ガードレールも同様です。
出力ガードレールも同様です。
```python
from pydantic import BaseModel
@@ -182,12 +183,12 @@ async def main():
print("Math output guardrail tripped")
```
1. これは実際のエージェントの出力型です。
2. これはガードレールの出力型です。
3. これはエージェントの出力を受け取り、結果を返すガードレール関数です。
4. これはワークフローを定義する実際のエージェントです。
1. これは実際のエージェントの出力型です。
2. これはガードレールの出力型です。
3. これはエージェントの出力を受け取り、実行結果を返すガードレール関数です。
4. これはワークフローを定義する実際のエージェントです。
最後に、ツールガードレールの例を示します。
最後に、ツールガードレールのコード例を示します。
```python
import json
+41 -41
View File
@@ -4,21 +4,21 @@ search:
---
# ハンドオフ
ハンドオフを使うと、あるエージェント別のエージェントにタスクを委譲できます。これは、異なるエージェントがそれぞれ異なる領域を専門にしているシナリオで特に有用です。たとえば、カスタマーサポートアプリは、注文状況、返金、 FAQ などのタスクをそれぞれ専任で処理するエージェントを用意できます
ハンドオフにより、エージェントはタスクを別のエージェントに委任できます。これは、異なるエージェントがそれぞれ別の領域を専門とするシナリオで特に役立ちます。たとえば、カスタマーサポートアプリは、注文ステータス、返金、 FAQ などのタスクをそれぞれ専門に扱うエージェントがあるかもしれません
ハンドオフは LLM に対してツールとして表現されます。したがって、`Refund Agent` という名前のエージェントへのハンドオフがある場合、そのツール`transfer_to_refund_agent` になります。
ハンドオフは LLM に対してツールとして表現されます。そのため、 `Refund Agent` という名前のエージェントへのハンドオフがある場合、そのツールは `transfer_to_refund_agent` と呼ばれます。
## ハンドオフの作成
すべてのエージェントには [`handoffs`][agents.agent.Agent.handoffs] パラメーターがあり、`Agent` を直接渡すことも、ハンドオフをカスタマイズする `Handoff` オブジェクトを渡すこともできます。
すべてのエージェントには [`handoffs`][agents.agent.Agent.handoffs] パラメーターがあり、 `Agent` を直接受け取ることも、ハンドオフをカスタマイズする `Handoff` オブジェクトを受け取ることもできます。
プレーンな `Agent` インスタンスを渡す場合、[`handoff_description`][agents.agent.Agent.handoff_description](設定されている場合)がデフォルトのツール説明に追されます。これを使うと、完全な `handoff()` オブジェクトを書かなくても、どのときにそのハンドオフをモデルが選ぶべきかを示せます
通常の `Agent` インスタンスを渡す場合、その [`handoff_description`][agents.agent.Agent.handoff_description] (設定されている場合)がデフォルトのツール説明に追されます。完全な `handoff()` オブジェクトを書かずに、そのハンドオフをモデルが選ぶべきタイミングを示唆するために使用してください
Agents SDK が提供する [`handoff()`][agents.handoffs.handoff] 関数を使てハンドオフを作成できます。この関数では、ハンドオフ先のエージェントに加えて、任意のオーバーライドや input filter を指定できます。
Agents SDK が提供する [`handoff()`][agents.handoffs.handoff] 関数を使用してハンドオフを作成できます。この関数では、必要に応じた上書きや入力フィルターとともに、引き渡し先のエージェントを指定できます。
### 基本的な使い方
### 基本的な使用法
シンプルなハンドオフは次のように作成できます。
シンプルなハンドオフを作成する方法は次のとおりです。
```python
from agents import Agent, handoff
@@ -30,22 +30,22 @@ refund_agent = Agent(name="Refund agent")
triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, handoff(refund_agent)])
```
1. エージェントを直接`billing_agent` のように)使うことも`handoff()` 関数を使こともできます。
1. エージェントを直接使用することも( `billing_agent` のように)、 `handoff()` 関数を使用することもできます。
### `handoff()` 関数によるハンドオフのカスタマイズ
[`handoff()`][agents.handoffs.handoff] 関数を使と、さまざまなカスタマイズできます。
[`handoff()`][agents.handoffs.handoff] 関数を使用すると、さまざまな項目をカスタマイズできます。
- `agent`: ハンドオフ先のエージェントです。
- `tool_name_override`: デフォルトでは `Handoff.default_tool_name()` 関数が使れ、`transfer_to_<agent_name>` に解決されます。これをオーバーライドできます。
- `tool_description_override`: `Handoff.default_tool_description()` デフォルトツール説明をオーバーライドします。
- `on_handoff`: ハンドオフが呼び出されたときに実行されるコールバック関数です。ハンドオフ呼び出が分かった時点でデータ取得を開始する、といった用途に有用です。この関数はエージェントコンテキストを受け取り、任意で LLM が生成した入力も受け取れます。入力データは `input_type` パラメーター制御されます。
- `input_type`: ハンドオフツール呼び出し引数のスキーマです。設定すると、パース済みペイロードが `on_handoff` に渡されます。
- `input_filter`: 次のエージェントが受け取る入力をフィルタリングできます。詳細は下を参照してください。
- `is_enabled`: ハンドオフ有効にするかどうかです。boolean または boolean を返す関数を指定でき、実行時に動的に有効 / 無効を切り替えられます。
- `nest_handoff_history`: RunConfig レベルの `nest_handoff_history` 設定を呼び出し単位で上書きする任意設定です。`None` の場合、アクティブな実行設定で定義された値が代わりに使れます。
- `agent`: 処理を引き渡す先のエージェントです。
- `tool_name_override`: デフォルトでは `Handoff.default_tool_name()` 関数が使用され、 `transfer_to_<agent_name>` に解決されます。これは上書きできます。
- `tool_description_override`: `Handoff.default_tool_description()` から得られるデフォルトツール説明を上書きします。
- `on_handoff`: ハンドオフが呼び出されたときに実行されるコールバック関数です。ハンドオフ呼び出されることが分かった時点ですぐにデータ取得を開始する、といった用途に便利です。この関数はエージェントコンテキストを受け取り、任意で LLM が生成した入力も受け取れます。入力データは `input_type` パラメーターによって制御されます。
- `input_type`: ハンドオフツール呼び出し引数のスキーマです。設定されている場合、解析されたペイロードが `on_handoff` に渡されます。
- `input_filter`: これにより、次のエージェントが受け取る入力をフィルタリングできます。詳細は下を参照してください。
- `is_enabled`: ハンドオフ有効かどうかです。これはブール値、またはブール値を返す関数でき、実行時にハンドオフを動的に有効化または無効化できます。
- `nest_handoff_history`: RunConfig レベルの `nest_handoff_history` 設定に対する、呼び出しごとの任意の上書きです。 `None` の場合、アクティブな実行設定で定義された値が代わりに使用されます。
[`handoff()`][agents.handoffs.handoff] ヘルパーは、常に渡された特定の `agent` に制御を移します。遷移先候補が複数ある場合は、遷移先ごとにハンドオフを 1 つずつ登録し、モデルにその中から選ばせてください。独自のハンドオフコードが呼び出し時に返すエージェントを決定する必要がある場合にのみ、カスタム [`Handoff`][agents.handoffs.Handoff] を使用してください。
[`handoff()`][agents.handoffs.handoff] ヘルパーは、渡された特定の `agent`常に制御を移します。複数の宛先候補がある場合は、先ごとに 1 つのハンドオフを登録し、モデルにその中から選ばせてください。独自のハンドオフコードが呼び出し時にどのエージェントを返すかを決定する必要がある場合にのみ、カスタム [`Handoff`][agents.handoffs.Handoff] を使用してください。
```python
from agents import Agent, handoff, RunContextWrapper
@@ -65,7 +65,7 @@ handoff_obj = handoff(
## ハンドオフ入力
状況によっては、ハンドオフを呼び出すときに LLM にデータをしてほしいことがあります。たとえば「Escalation agent」へのハンドオフを考えてみてください。ログに記録できるよう理由をしてほしい場合があります。
状況によっては、 LLM がハンドオフを呼び出すときに何らかのデータを提供してほしい場合があります。たとえば、「エスカレーションエージェント」へのハンドオフを想像してみてください。ログに記録できるように、モデルに理由を提供してほしい場合があります。
```python
from pydantic import BaseModel
@@ -87,44 +87,44 @@ handoff_obj = handoff(
)
```
`input_type` は、ハンドオフツール呼び出し自体の引数を記述します。SDK はそのスキーマをハンドオフツールの `parameters` としてモデルに公開し、返された JSON をローカルで検証して、パース済みの値を `on_handoff` に渡します。
`input_type` は、ハンドオフツール呼び出し自体の引数をします。 SDK はそのスキーマをハンドオフツールの `parameters` としてモデルに公開し、返された JSON をローカルで検証して、解析済みの値を `on_handoff` に渡します。
これは次のエージェントのメイン入力を置き換えるものではなく、遷移先を変更するものでもありません。[`handoff()`][agents.handoffs.handoff] ヘルパーは引き続きラップした特定のエージェントへハンドオフします。また、受信側エージェントは[`input_filter`][agents.handoffs.Handoff.input_filter] ネストされたハンドオフ履歴設定で変更しない限り、会話履歴を引き続き参照します。
これは次のエージェントのメイン入力を置き換えるものではなく、別の宛先を選択するものでもありません。 [`handoff()`][agents.handoffs.handoff] ヘルパーは引き続きラップした特定のエージェントへ転送し、受け取り側のエージェントは [`input_filter`][agents.handoffs.Handoff.input_filter] またはネストされたハンドオフ履歴設定で変更しない限り、引き続き会話履歴を参照します。
`input_type` は [`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] とも別物です。`input_type` は、ハンドオフ時にモデルが決定するメタデータに使い、ローカルすでに持っているアプリケーション状態や依存関係には使わないでください。
`input_type` は [`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] とも別のものです。ローカルすでにるアプリケーション状態や依存関係ではなく、ハンドオフ時にモデルが決定するメタデータには `input_type` を使用してください。
### `input_type` を使うタイミング
### `input_type` の使用タイミング
ハンドオフに `reason``language``priority``summary` のような、モデル生成小さなメタデータが必要な場合に `input_type` を使てください。たとえば、トリアージエージェントは `{ "reason": "duplicate_charge", "priority": "high" }` を付けて返金エージェントへハンドオフでき、`on_handoff` は返金エージェントに制御が移る前にそのメタデータをログ化または永続化できます。
ハンドオフに `reason``language``priority``summary`、モデル生成する小さなメタデータが必要な場合に `input_type` を使用してください。たとえば、トリアージエージェントは `{ "reason": "duplicate_charge", "priority": "high" }` とともに返金エージェントへハンドオフでき、返金エージェントが引き継ぐ前に `on_handoff` でそのメタデータをログに記録したり永続化したりできます。
目的が異なる場合は、別の仕組みを選んでください。
- 既存のアプリケーション状態と依存関係は [`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] に入れてください。[context ガイド](context.md)を参照してください。
-信側エージェントがる履歴を変更したい場合は、[`input_filter`][agents.handoffs.Handoff.input_filter][`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history]、または [`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] を使てください。
- 複数の専門エージェント候補ある場合は、遷移先ごとにハンドオフを 1 つずつ登録してください。`input_type` は選れたハンドオフにメタデータを追加できますが、遷移先の振り分けはません。
- 会話を転送せずにネストされた専門エージェント向けの構造化入力が欲しい場合は、[`Agent.as_tool(parameters=...)`][agents.agent.Agent.as_tool] を優先してください。[tools](tools.md#structured-input-for-tool-agents)を参照してください。
- 既存のアプリケーション状態と依存関係は [`RunContextWrapper.context`][agents.run_context.RunContextWrapper.context] に置いてください。[コンテキストガイド](context.md)を参照してください。
-け取り側のエージェントが参照する履歴を変更したい場合は、 [`input_filter`][agents.handoffs.Handoff.input_filter][`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history] 、または [`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] を使用してください。
- 複数の専門エージェント候補ある場合は、先ごとに 1 つのハンドオフを登録してください。 `input_type` は選択されたハンドオフにメタデータを追加できますが、宛先間の振り分けは行いません。
- 会話を引き渡さずにネストされた専門エージェント構造化入力を渡したい場合は、 [`Agent.as_tool(parameters=...)`][agents.agent.Agent.as_tool] を優先してください。[ツール](tools.md#structured-input-for-tool-agents)を参照してください。
## input filter
## 入力フィルター
ハンドオフが発生すると、新しいエージェントが会話を引き継ぎ、以前の会話履歴全体を参照できる状態になります。これを変更したい場合は、[`input_filter`][agents.handoffs.Handoff.input_filter] を設定できます。input filter は、既存入力を [`HandoffInputData`][agents.handoffs.HandoffInputData] 経由で受け取り、新しい `HandoffInputData` を返す関数です。
ハンドオフが発生すると、新しいエージェントが会話を引き継ぎ、以前の会話履歴全体を参照できるようになります。これを変更したい場合は、 [`input_filter`][agents.handoffs.Handoff.input_filter] を設定できます。入力フィルターは、 [`HandoffInputData`][agents.handoffs.HandoffInputData] を通じて既存の入力を受け取り、新しい `HandoffInputData` を返す必要がある関数です。
[`HandoffInputData`][agents.handoffs.HandoffInputData] には次が含まれます。
- `input_history`: `Runner.run(...)` 開始前の入力履歴。
- `pre_handoff_items`: ハンドオフが呼び出されたエージェントターンより前に生成されたアイテム。
- `new_items`: 現在のターン中に生成されたアイテム(ハンドオフ呼び出しとハンドオフ出力アイテムを含む
- `input_items`: `new_items` の代わりに次のエージェントへ渡す任意のアイテム。これにより、セッション履歴用に `new_items`保ったまま、モデル入力をフィルタリングできす。
- `run_context`: ハンドオフ呼び出時点でアクティブな [`RunContextWrapper`][agents.run_context.RunContextWrapper]。
- `input_history`: `Runner.run(...)` 開始する前の入力履歴です
- `pre_handoff_items`: ハンドオフが呼び出されたエージェントターンより前に生成されたアイテムです
- `new_items`: ハンドオフ呼び出しとハンドオフ出力アイテムを含む、現在のターン中に生成されたアイテムです
- `input_items`: セッション履歴用に `new_items`そのまま保ちながらモデル入力をフィルタリングできるよう、 `new_items` の代わりに次のエージェントへ転送する任意のアイテムです。
- `run_context`: ハンドオフ呼び出された時点でアクティブな [`RunContextWrapper`][agents.run_context.RunContextWrapper] です
ネストされたハンドオフは opt-in のベータとして提供されており、安定化のためデフォルトで無効です。[`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history] を有効にすると、runner はそれまでの transcript を 1 つの assistant 要約メッセージに折りたたみ、同一 run 中に複数のハンドオフが起きると新しいターンが追記され続ける `<CONVERSATION HISTORY>` ブロック包みます。完全な `input_filter` を書かずに生成メッセージを置き換えたい場合は、[`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] 独自のマッピング関数を渡せます。この opt-in は、ハンドオフ側と run 側のいずれも明示的な `input_filter` を指定していない場合にのみ適用されるため、すでにペイロードをカスタマイズしている既存コード(このリポジトリのコード例を含む)は変更なしで現在の動を維持します。[`handoff(...)`][agents.handoffs.handoff] に `nest_handoff_history=True` または `False` を渡すことで、単一ハンドオフのネスト挙動を上書きできますこれ [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history] 設定ます。生成要約のラッパーテキストだけを変更したい場合は、エージェント実行前に [`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers](必要に応じて [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers])を呼び出してください
ネストされたハンドオフはオプトインのベータとして利用でき、安定化が進むまではデフォルトで無効です。 [`RunConfig.nest_handoff_history`][agents.run.RunConfig.nest_handoff_history] を有効にすると、ランナーは以前の会話記録を 1 つの assistant 要約メッセージにまとめ、それを `<CONVERSATION HISTORY>` ブロック包みます。このブロックには、同じ実行中に複数のハンドオフが発生した場合に新しいターンが追加され続けます。 [`RunConfig.handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper] を通じて独自のマッピング関数を提供し、完全な `input_filter` を書くことなく、生成されたメッセージを置き換えることができます。このオプトインは、ハンドオフと実行のどちらも明示的な `input_filter` を指定していない場合にのみ適用されます。そのため、ペイロードをすでにカスタマイズしている既存コード(このリポジトリのコード例を含む)は変更なしで現在の動を維持します。単一のハンドオフに対してネスト動作を上書きするには、 [`handoff(...)`][agents.handoffs.handoff] に `nest_handoff_history=True` または `False` を渡ますこれにより [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history] 設定されます。生成された要約のラッパーテキストだけを変更したい場合は、エージェント実行する前に [`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] を呼び出してください(必要に応じて [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers]呼び出せます)
ハンドオフとアクティブな [`RunConfig.handoff_input_filter`][agents.run.RunConfig.handoff_input_filter] の両方フィルター定義されている場合、その特定ハンドオフではハンドオフ単位の [`input_filter`][agents.handoffs.Handoff.input_filter] が優先されます。
ハンドオフとアクティブな [`RunConfig.handoff_input_filter`][agents.run.RunConfig.handoff_input_filter] の両方フィルター定義ている場合、その特定ハンドオフではハンドオフごとの [`input_filter`][agents.handoffs.Handoff.input_filter] が優先されます。
!!! note
ハンドオフは単一の run 内に留まります。入力ガードレールは依然としてチェーン内の最初のエージェントにのみ適用され、出力ガードレールは最終出力を生成するエージェントにのみ適用されます。ワークフロー内の各カスタム function-tool 呼び出しごとにチェックが必要な場合は、ツールガードレールを使用してください。
ハンドオフは単一の実行内にとどまります。入力ガードレールは引き続きチェーン内の最初のエージェントにのみ適用され、出力ガードレールは最終出力を生成するエージェントにのみ適用されます。ワークフロー内の各カスタム関数ツール呼び出しの周囲でチェックが必要な場合は、ツールガードレールを使用してください。
一般的なパターン(たとえば履歴からすべてのツール呼び出しを削除するなど)は、[`agents.extensions.handoff_filters`][] に実装されています。
一般的なパターン(たとえば履歴からすべてのツール呼び出しを削除するなど)がいくつかあり、 [`agents.extensions.handoff_filters`][] に実装されています。
```python
from agents import Agent, handoff
@@ -138,11 +138,11 @@ handoff_obj = handoff(
)
```
1. これにより、`FAQ agent` が呼び出されたときに履歴からすべてのツールが自動的に削除されます。
1. これにより、 `FAQ agent` が呼び出されたときに履歴からすべてのツールが自動的に削除されます。
## 推奨プロンプト
LLM がハンドオフを適切に理解できるように、エージェントにハンドオフ情報を含めることを推奨します。[`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] に推奨プレフィックスがあり、または [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] を呼び出して、推奨データをプロンプトに自動追加できます。
LLM がハンドオフを適切に理解できるように、エージェントにハンドオフに関する情報を含めることを推奨します。推奨されるプレフィックスを [`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] に用意しています。または [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] を呼び出して、推奨データをプロンプトに自動的に追加できます。
```python
from agents import Agent
+52 -60
View File
@@ -2,19 +2,19 @@
search:
exclude: true
---
# Human-in-the-loop
# ヒューマンインザループ
human-in-the-loop ( HITL ) フローを使用すると、機密性の高いツール呼び出しを人が承認または拒否するまで、エージェント実行を一時停止できます。ツールは承認が必要なタイミングを宣言し、実行結果は保留中の承認を中断として示し、`RunState` によって判後に実行をシリアライズおよび再開できます。
ヒューマンインザループ (HITL) フローを使用すると、人が慎重な扱いが必要なツール呼び出しを承認または拒否するまで、エージェント実行を一時停止できます。ツールは承認が必要なタイミングを宣言し、実行結果は保留中の承認を中断として示し、`RunState` によって判後に実行をシリアライズして再開できます。
の承認サーフェスは実行全体に適用され、現在のトップレベルエージェントに限定されません。同じパターンは、ツールが現在のエージェントに属する場合、ハンドオフ到達したエージェントに属する場合、またはネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行に属する場合にも適用されます。ネストされた `Agent.as_tool()` の場合でも、中断は外側の実行に示されるため、外側の `RunState` で承認または拒否し、元のトップレベル実行を再開します。
の承認の提示先は実行全体であり、現在のトップレベルエージェントに限定されません。同じパターンは、ツールが現在のエージェントに属する場合、ハンドオフを通じて到達したエージェントに属する場合、またはネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行に属する場合にも適用されます。ネストされた `Agent.as_tool()` の場合でも、中断は外側の実行に示されるため、外側の `RunState` で承認または拒否し、元のトップレベル実行を再開します。
`Agent.as_tool()` では、承認 2 つの異なるレイヤーで発生する可能性があります。エージェントツール自体が `Agent.as_tool(..., needs_approval=...)` によって承認を要求でき、さらにネストされたエージェント内のツールネスト実行開始後に独自の承認を発生させることもできます。どちらも同じ外側実行の中断フロー処理されます。
`Agent.as_tool()` では、承認 2 つの異なるレイヤーで発生する可能性があります。エージェントツール自体が `Agent.as_tool(..., needs_approval=...)` によって承認を要求でき、ネストされたエージェント内のツールも、ネストされた実行開始した後に独自の承認を要求できます。どちらも同じ外側実行の中断フローを通じて処理されます。
このページでは、`interruptions` を介した手動承認フローに焦点を当てます。アプリがコードで判できる場合、一部のツールタイプはプログラムによる承認コールバックもサポートしており、実行を一時停止せずに続できます。
このページでは、`interruptions` を介した手動承認フローに焦点を当てます。アプリがコードで判できる場合、一部のツールタイプはプログラムによる承認コールバックにも対応しているため、実行を一時停止せずに続できます。
## 承認が必要なツールのマーキング
## 承認が必要なツールの指定
`needs_approval``True` に設定すると常に承認が必要になり、呼び出しごとに判する非同期関数を渡すこともできます。呼び出し可能オブジェクトは、実行コンテキスト、解析済みツールパラメーター、ツール呼び出し ID を受け取ります。
常に承認を要求するには `needs_approval``True` に設定する、呼び出しごとに判する async 関数を指定します。この呼び出し可能オブジェクトは、実行コンテキスト、解析済みツールパラメーター、ツール呼び出し ID を受け取ります。
```python
from agents import Agent, Runner, function_tool
@@ -41,28 +41,28 @@ agent = Agent(
)
```
`needs_approval` [`function_tool`][agents.tool.function_tool]、[`Agent.as_tool`][agents.agent.Agent.as_tool]、[`ShellTool`][agents.tool.ShellTool]、[`ApplyPatchTool`][agents.tool.ApplyPatchTool] で利用できます。ローカル MCP サーバーも、[`MCPServerStdio`][agents.mcp.server.MCPServerStdio]、[`MCPServerSse`][agents.mcp.server.MCPServerSse]、[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] の `require_approval` を通じて承認をサポートします。ホスト型 MCP サーバーは、[`HostedMCPTool`][agents.tool.HostedMCPTool] の `tool_config={"require_approval": "always"}`任意の `on_approval_request` コールバックを介して承認をサポートします。 shell および apply_patch ツールは、割り込みを表示せずに自動承認または自動拒否したい場合に `on_approval` コールバックを受け付けます。
`needs_approval`[`function_tool`][agents.tool.function_tool]、[`Agent.as_tool`][agents.agent.Agent.as_tool]、[`ShellTool`][agents.tool.ShellTool]、[`ApplyPatchTool`][agents.tool.ApplyPatchTool] で利用できます。ローカル MCP サーバーも、[`MCPServerStdio`][agents.mcp.server.MCPServerStdio]、[`MCPServerSse`][agents.mcp.server.MCPServerSse]、[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] の `require_approval` を通じて承認に対応しています。ホスト型 MCP サーバーは、`tool_config={"require_approval": "always"}` と任意の `on_approval_request` コールバックを設定した [`HostedMCPTool`][agents.tool.HostedMCPTool] によって承認に対応します。Shell apply_patch ツールは、中断を提示せずに自動承認または自動拒否したい場合に `on_approval` コールバックを受け付けます。
## 承認フローの仕組み
1. モデルがツール呼び出しを出力すると、ランナーはその承認ルール (`needs_approval``require_approval`、またはホスト型 MCP の同等機能) を評価します。
2. そのツール呼び出しに対する承認判がすでに [`RunContextWrapper`][agents.run_context.RunContextWrapper] に保存されている場合、ランナーは確認なしで続行します。呼び出し単位の承認は特定の呼び出し ID にスコープされます。実行の残り期間における同ツールへの今後の呼び出しにも同じ判を保持するには、`always_approve=True` または `always_reject=True` を渡します。
3. それ以外の場合、実行は一時停止し、`RunResult.interruptions` (または `RunResultStreaming.interruptions`) に `agent.name``tool_name``arguments` などの詳細を含む [`ToolApprovalItem`][agents.items.ToolApprovalItem] エントリが入ります。これには、ハンドオフ後またはネストされた `Agent.as_tool()` 実行内で発生した承認も含まれます。
4. `result.to_state()`結果を `RunState` に変換し、`state.approve(...)` または `state.reject(...)` を呼び出した後`Runner.run(agent, state)` または `Runner.run_streamed(agent, state)` で再開します。ここで `agent` は、その実行元のトップレベルエージェントです。
5. 再開された実行は中断地点から継続し、新たな承認が必要であればこのフローに再入ります。
2. そのツール呼び出し承認判がすでに [`RunContextWrapper`][agents.run_context.RunContextWrapper] に保存されている場合、ランナーは確認を求めずに処理を続行します。呼び出しごとの承認は特定の呼び出し ID にスコープされます。そのツールに対する今後の呼び出しに、実行の残りの間同じ判を保持するには、`always_approve=True` または `always_reject=True` を渡します。
3. それ以外の場合、実行は一時停止し、`RunResult.interruptions` (または `RunResultStreaming.interruptions`) に`agent.name``tool_name``arguments` などの詳細を含む [`ToolApprovalItem`][agents.items.ToolApprovalItem] エントリが入ります。これには、ハンドオフ後ネストされた `Agent.as_tool()` 実行内で発生した承認も含まれます。
4. 実行結果を `result.to_state()``RunState` に変換し、`state.approve(...)` または `state.reject(...)` を呼び出してから`Runner.run(agent, state)` または `Runner.run_streamed(agent, state)` で再開します。ここで `agent` は、その実行における元のトップレベルエージェントです。
5. 再開された実行は中断した場所から続行し、新しい承認が必要になった場合はこのフローに再入ります。
`always_approve=True` または `always_reject=True` で作成された固定判は実行状態に保存されるため、同じ一時停止済み実行を後で再開する`state.to_string()` / `RunState.from_string(...)` および `state.to_json()` / `RunState.from_json(...)`またいで保持されます。
`always_approve=True` または `always_reject=True` で作成された固定判は実行状態に保存されるため、後で同じ一時停止中の実行を再開するとき`state.to_string()` / `RunState.from_string(...)` および `state.to_json()` / `RunState.from_json(...)`使っても保持されます。
同じパスで保留中承認をすべて解決する必要はありません。`interruptions` には、通常の関数ツール、ホスト型 MCP 承認、ネストされた `Agent.as_tool()` 承認が混在する可能性があります。一部の項目のみ承認または拒否して再実行した場合、解決済みの呼び出しは継続し、未解決のものは `interruptions` に残って実行を再び一時停止します。
すべての保留中承認を同じ 1 回の処理で解決する必要はありません。`interruptions` には、通常の関数ツール、ホスト型 MCP 承認、ネストされた `Agent.as_tool()` 承認が混在する場合があります。一部の項目だけを承認または拒否した後に再実行すると、解決済みの呼び出しは続行でき、未解決のものは `interruptions` に残って実行を再び一時停止します。
## 拒否メッセージのカスタマイズ
## カスタム拒否メッセージ
デフォルトでは、拒否されたツール呼び出しは SDK 標準拒否テキストを実行に返します。このメッセージは 2 つのレイヤーでカスタマイズできます。
既定では、拒否されたツール呼び出しは SDK 標準拒否テキストを実行に返します。このメッセージは 2 つのレイヤーでカスタマイズできます。
- 実行全体のフォールバック: [`RunConfig.tool_error_formatter`][agents.run.RunConfig.tool_error_formatter] を設定し、実行全体の承認拒否に対するモデル可視のデフォルトメッセージを制御します。
- 呼び出し単位の上書き: 特定の拒否ツール呼び出しだけメッセージを示したい場合、`state.reject(...)``rejection_message=...` を渡します。
- 実行全体のフォールバック: 実行全体で承認拒否に対するモデルに見える既定メッセージを制御するには、[`RunConfig.tool_error_formatter`][agents.run.RunConfig.tool_error_formatter] を設定します。
- 呼び出しごとのオーバーライド: 特定の拒否されたツール呼び出しだけに異なるメッセージを示したい場合`state.reject(...)``rejection_message=...` を渡します。
両方が指定され場合、呼び出し単位`rejection_message` が実行全体フォーマッターより優先されます。
両方が指定されている場合、呼び出しごと`rejection_message` が実行全体フォーマッターより優先されます。
```python
from agents import RunConfig, ToolErrorFormatterArgs
@@ -83,27 +83,27 @@ state.reject(
)
```
両レイヤーを組み合わせて示す完全な例は [`examples/agent_patterns/human_in_the_loop_custom_rejection.py`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns/human_in_the_loop_custom_rejection.py) を参照してください。
方のレイヤーをまとめて示す完全なコード例については、[`examples/agent_patterns/human_in_the_loop_custom_rejection.py`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns/human_in_the_loop_custom_rejection.py) を参照してください。
## 自動承認判
## 自動承認判
手動 `interruptions` は最も汎用的なパターンですが、唯一ではありません。
手動 `interruptions` は最も汎用的なパターンですが、唯一の方法ではありません。
- ローカル [`ShellTool`][agents.tool.ShellTool] と [`ApplyPatchTool`][agents.tool.ApplyPatchTool] は `on_approval` を使用してコード内で即に承認または拒否できます。
- [`HostedMCPTool`][agents.tool.HostedMCPTool] は、同種のプログラムによる判断のために `tool_config={"require_approval": "always"}``on_approval_request`併用できます。
- 通常の [`function_tool`][agents.tool.function_tool] ツールと [`Agent.as_tool()`][agents.agent.Agent.as_tool] は、このページの手動中断フローを使用します。
- ローカル [`ShellTool`][agents.tool.ShellTool] と [`ApplyPatchTool`][agents.tool.ApplyPatchTool] は`on_approval` を使用してコード内で即に承認または拒否できます。
- [`HostedMCPTool`][agents.tool.HostedMCPTool] は、`tool_config={"require_approval": "always"}``on_approval_request`組み合わせて、同じ種類のプログラムによる判定を行えます。
- 通常の [`function_tool`][agents.tool.function_tool] ツールと [`Agent.as_tool()`][agents.agent.Agent.as_tool] は、このページの手動中断フローを使用します。
これらのコールバックが判を返すと、実行は人の応答を待って一時停止せずに継続します。 Realtime および音声セッション API については、[Realtime ガイド](realtime/guide.md) の承認フローを参照してください。
これらのコールバックが判を返すと、人の応答を待って一時停止することなく実行が続行されます。Realtime および音声セッション API については、[Realtime ガイド](realtime/guide.md) の承認フローを参照してください。
## ストリーミングとセッション
同じ中断フローはストリーミング実行でも機能します。ストリーミング実行が一時停止した、イテレーターが終了するまで [`RunResultStreaming.stream_events()`][agents.result.RunResultStreaming.stream_events] を消費し、[`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] を確認して解決し、再開後の出力もストリーミングを継続したい場合は [`Runner.run_streamed(...)`][agents.run.Runner.run_streamed] で再開します。このパターンのストリーミング版[ストリーミング](streaming.md) を参照してください。
同じ中断フローはストリーミング実行でも機能します。ストリーミング実行が一時停止した後は、イテレーターが終了するまで [`RunResultStreaming.stream_events()`][agents.result.RunResultStreaming.stream_events] を消費し続け、[`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] を確認して解決し、再開後の出力もストリーミングし続けたい場合は [`Runner.run_streamed(...)`][agents.run.Runner.run_streamed] で再開します。このパターンのストリーミング版については、[ストリーミング](streaming.md) を参照してください。
セッションも使用している場合は、`RunState` から再開するに同じセッションインスタンスを渡し続けるか、同じバックエンドストアを指す別のセッションオブジェクトを渡してください。再開されたターンは同じ保存済み会話履歴に追加されます。セッションライフサイクル詳細[セッション](sessions/index.md) を参照してください。
セッションも使用している場合は、`RunState` から再開するときに同じセッションインスタンスを渡し続けるか、同じバッキングストアを指す別のセッションオブジェクトを渡します。これにより、再開されたターンは同じ保存済み会話履歴に追加されます。セッションライフサイクル詳細については、[セッション](sessions/index.md) を参照してください。
## 例: 一時停止承認再開
## 例: 一時停止承認再開
以下のスニペットは JavaScript の HITL ガイドを踏襲しています。ツールに承認が必要なときに一時停止し、状態をディスクに保存し、再読み込みし、判を収集した後に再開します。
以下のスニペットは JavaScript の HITL ガイドと同じ流れです。ツールに承認が必要な場合に一時停止し、状態をディスクに永続化して再読み込みし、判を収集した後に再開します。
```python
import asyncio
@@ -167,43 +167,35 @@ if __name__ == "__main__":
asyncio.run(main())
```
この例では、`prompt_approval``input()` を使用し `run_in_executor(...)` で実行されるため同期的です。承認ソースがすでに非同期 ( 例: HTTP リクエストや非同期データベースクエリ) の場合は`async def` 関数を使用して直接 `await` できます。
この例では、`prompt_approval``input()` を使用し`run_in_executor(...)` で実行されるため同期的です。承認の取得元がすでに非同期である場合 (たとえば、HTTP リクエストや非同期データベースクエリ)、代わりに `async def` 関数を使用して直接 `await` できます。
承認待ち中にも出力をストリーミングしたい場合は、`Runner.run_streamed` を呼び出し、完了まで `result.stream_events()` を消費し、その後は上記と同じ `result.to_state()` と再開手順に従ってください。
承認を待つ間に出力をストリーミングするには、`Runner.run_streamed` を呼び出し、完了するまで `result.stream_events()` を消費してから、上記と同じ `result.to_state()` と再開手順に従います
## リポジトリのパターンと例
## リポジトリのパターンとコード
- **ストリーミング承認**: `examples/agent_patterns/human_in_the_loop_stream.py` は、`stream_events()` を最後まで処理し、保留中ツール呼び出しを承認してから `Runner.run_streamed(agent, state)` で再開する方法を示します。
- **カスタム拒否テキスト**: `examples/agent_patterns/human_in_the_loop_custom_rejection.py` は、承認が拒否されたときに実行レベルの `tool_error_formatter` と呼び出し単位`rejection_message` 上書きを組み合わせる方法を示します。
- **Agent as tool 承認**: `Agent.as_tool(..., needs_approval=...)` は、委譲されたエージェントタスクにレビューが必要な場合に同じ中断フローを適用します。ネストされた中断も外側の実行に示されるため、ネストではなく元のトップレベルエージェントを再開してください。
- **ローカル shell / apply_patch ツール**: `ShellTool``ApplyPatchTool``needs_approval` をサポートします。将来の呼び出しのために判断をキャッシュするには `state.approve(interruption, always_approve=True)` または `state.reject(..., always_reject=True)` を使用します。自動判には `on_approval` を指定します ( `examples/tools/shell.py` を参照)。手動判には中断を処理します ( `examples/tools/shell_human_in_the_loop.py` を参照)。ホスト型 shell 環境は `needs_approval` または `on_approval` をサポートしません。[ツールガイド](tools.md) を参照してください。
- **ローカル MCP サーバー**: `MCPServerStdio` / `MCPServerSse` / `MCPServerStreamableHttp` `require_approval` を使用し、MCP ツール呼び出しを制御します ( `examples/mcp/get_all_mcp_tools_example/main.py` および `examples/mcp/tool_filter_example/main.py` を参照)。
- **ホスト型 MCP サーバー**: HITL を強制するには `HostedMCPTool``require_approval``"always"` に設定し、必要に応じて `on_approval_request` を指定して自動承認または拒否します ( `examples/hosted_mcp/human_in_the_loop.py` および `examples/hosted_mcp/on_approval.py` を参照)。信頼済みサーバーには `"never"` を使用します (`examples/hosted_mcp/simple.py`)。
- **セッションとメモリ**: 複数ターンにわたり承認と会話履歴を保持するには `Runner.run` にセッションを渡します。 SQLite および OpenAI Conversations セッションのバリアントは `examples/memory/memory_session_hitl_example.py``examples/memory/openai_session_hitl_example.py` にあります。
- **Realtime エージェント**: realtime デモ`RealtimeSession``approve_tool_call` / `reject_tool_call` を介してツール呼び出しを承認または拒否する WebSocket メッセージを公開します ( サーバー側ハンドラーは `examples/realtime/app/server.py`、API サーフェスは [Realtime ガイド](realtime/guide.md#tool-approvals) を参照)。
- **ストリーミング承認**: `examples/agent_patterns/human_in_the_loop_stream.py` は、`stream_events()` を最後まで読み出し、その後 `Runner.run_streamed(agent, state)` で再開する前に保留中のツール呼び出しを承認する方法を示します。
- **カスタム拒否テキスト**: `examples/agent_patterns/human_in_the_loop_custom_rejection.py` は、承認が拒否された場合に、実行レベルの `tool_error_formatter` と呼び出しごと`rejection_message` オーバーライドを組み合わせる方法を示します。
- **ツールとしてのエージェントの承認**: `Agent.as_tool(..., needs_approval=...)` は、委譲されたエージェントタスクにレビューが必要な場合に同じ中断フローを適用します。ネストされた中断も外側の実行に示されるため、ネストされたエージェントではなく元のトップレベルエージェントを再開してください。
- **ローカル shell apply_patch ツール**: `ShellTool``ApplyPatchTool``needs_approval` に対応しています。将来の呼び出しに備えて判定をキャッシュするには`state.approve(interruption, always_approve=True)` または `state.reject(..., always_reject=True)` を使用します。自動判には `on_approval` を指定します (`examples/tools/shell.py` を参照)。手動判には中断を処理します (`examples/tools/shell_human_in_the_loop.py` を参照)。ホスト型 shell 環境は `needs_approval` または `on_approval` に対応していません。[ツールガイド](tools.md) を参照してください。
- **ローカル MCP サーバー**: MCP ツール呼び出しを制御するには、`MCPServerStdio` / `MCPServerSse` / `MCPServerStreamableHttp` `require_approval` を使用します (`examples/mcp/get_all_mcp_tools_example/main.py` `examples/mcp/tool_filter_example/main.py` を参照)。
- **ホスト型 MCP サーバー**: HITL を強制するには`HostedMCPTool``require_approval``"always"` に設定し、必要に応じて自動承認または拒否のために `on_approval_request` を指定します (`examples/hosted_mcp/human_in_the_loop.py` `examples/hosted_mcp/on_approval.py` を参照)。信頼済みサーバーには `"never"` を使用します (`examples/hosted_mcp/simple.py`)。
- **セッションとメモリ**: セッションを `Runner.run` に渡すと、承認と会話履歴が複数ターンにわたって保持されます。SQLite OpenAI Conversations セッション版は、`examples/memory/memory_session_hitl_example.py``examples/memory/openai_session_hitl_example.py` にあります。
- **Realtime エージェント**: Realtime デモでは、`RealtimeSession``approve_tool_call` / `reject_tool_call` を介してツール呼び出しを承認または拒否する WebSocket メッセージを公開しています (サーバー側ハンドラーについて`examples/realtime/app/server.py`、API サーフェスについては [Realtime ガイド](realtime/guide.md#tool-approvals) を参照)。
## 長時間実行承認
## 長時間にわたる承認
`RunState`永続性を考慮して設計されています。保留中作業をデータベースやキューに保存するには `state.to_json()` または `state.to_string()` を使用し、後で `RunState.from_json(...)` または `RunState.from_string(...)` で再作成します。
`RunState`耐久性を持つように設計されています。`state.to_json()` または `state.to_string()` を使用して保留中の作業をデータベースまたはキューに保存し、後で `RunState.from_json(...)` または `RunState.from_string(...)` で再作成します。
有用なシリアライズオプション:
便利なシリアライズオプション:
- `context_serializer`: マッピング以外のコンテキストオブジェクトをどのようにシリアライズするかをカスタマイズします。
- `context_deserializer`: `RunState.from_json(...)` または `RunState.from_string(...)` で状態をロードするときに、マッピング以外のコンテキストオブジェクトを再構築します。
- `strict_context=True`: コンテキストがすでに
マッピングであるか、適切な serializer / deserializer を提供しない限り、シリアライズまたはデシリアライズを失敗させます
- `context_override`: 状態ロード時にシリアライズ済みコンテキストを置き換えます。これは
元のコンテキストオブジェクトを復元したくない場合に有用ですが、すでに
シリアライズ済みペイロードからそのコンテキストを削除するものではありません。
- `include_tracing_api_key=True`: 再開作業でも同じ認証情報でトレースをエクスポートし続ける必要がある場合に、
シリアライズされたトレースペイロードに tracing API キーを含めます。
- `context_serializer`: マッピングのコンテキストオブジェクトシリアライズ方法をカスタマイズします。
- `context_deserializer`: `RunState.from_json(...)` または `RunState.from_string(...)` で状態を読み込むときに、マッピングのコンテキストオブジェクトを再構築します。
- `strict_context=True`: コンテキストがすでにマッピングであるか、適切なシリアライザー / デシリアライザーを指定している場合を除き、シリアライズまたはデシリアライズを失敗させます。
- `context_override`: 状態を読み込むときに、シリアライズされたコンテキストを置き換えます。これは、元のコンテキストオブジェクトを復元したくない場合に便利ですが、すでにシリアライズ済みのペイロードからそのコンテキストを削除するわけではありません
- `include_tracing_api_key=True`: 再開された作業で同じ認証情報を使ってトレースのエクスポートを継続する必要がある場合、シリアライズされたトレースペイロードにトレーシング API キーを含めます。
シリアライズされた実行状態には、アプリコンテキストに加えて、承認、
使用量、シリアライズされた `tool_input`、ネストされた agent-as-tool 再開、トレースメタデータ、サーバー管理の
会話設定など、SDK 管理の実行時メタデータが含まれます。シリアライズ状態を保存または転送する予定がある場合は、
`RunContextWrapper.context` を永続化データとして扱い、意図的に
状態と一緒に移動させたい場合を除き、そこに秘密情報を置かないでください。
シリアライズされた実行状態には、アプリコンテキストに加えて、承認、使用量、シリアライズ済みの `tool_input`、ネストされた agent-as-tool の再開情報、トレースメタデータ、サーバー管理の会話設定など、SDK 管理のランタイムメタデータが含まれます。シリアライズされた状態を保存または送信する予定がある場合は、`RunContextWrapper.context` を永続化データとして扱い、状態と一緒に移動させる意図がある場合を除き、そこにシークレットを置かないでください。
## 保留タスクのバージョニング
## 保留タスクのバージョニング
承認がしばらく保留される可能性がある場合は、シリアライズ状態と一緒にエージェント定義または SDK のバージョンマーカーを保存してください。これにより、デシリアライズを対応するコードパスに振り分け、モデル、プロンプト、またはツール定義が変更されたの非互換性を回避できます。
承認がしばらく保留される可能性がある場合は、エージェント定義または SDK のバージョンマーカーを、シリアライズされた状態と一緒に保存してください。これにより、モデル、プロンプト、ツール定義が変更された場合の非互換性を避けるために、対応するコードパスへデシリアライズ処理を振り分けられます。
+55 -35
View File
@@ -4,33 +4,51 @@ search:
---
# OpenAI Agents SDK
[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) は、非常に少ない抽象化で、軽量かつ使いやすいパッケージとしてエージェント型 AI アプリを構築できるようにします。これは、以前のエージェント向け実験である [Swarm](https://github.com/openai/swarm/tree/main) を本番対応向けにアップグレードしたものです。Agents SDK は、非常に小さな基本コンポーネントのセットがあります
[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) は、抽象化をほとんど持たない軽量で使いやすいパッケージで、エージェント型 AI アプリを構築できるようにします。これは、以前のエージェント向け実験プロジェクトである [Swarm](https://github.com/openai/swarm/tree/main) を本番環境対応に発展させたものです。Agents SDK は、非常に少数の基本コンポーネントで構成されています:
- **エージェント**: instructions と tools を備えた LLM
- **Agents as tools / ハンドオフ**: エージェントが特定タスクのために他のエージェント委任できるようにします
- **エージェント**: 指示とツールを備えた LLM です
- **Agents as tools / ハンドオフ**: エージェントが特定タスク他のエージェント委任できるようにします
- **ガードレール**: エージェントの入力と出力の検証を可能にします
これらの基本コンポーネントは Python と組み合わせることで、ツールとエージェント間の複雑な関係を表現できるほど強力であり、急な学習コストなしに実運用アプリケーションを構築できます。さらに SDK には、エージェント型フローを可視化・デバッグできる組み込みの **トレーシング** があり、評価の実行や、アプリケーション向けモデルのファインチューニングまで可能です。
Python と組み合わせることで、これらの基本コンポーネントは、ツールとエージェント間の複雑な関係を表現するのに十分強力であり、習得のハードルを高くすることなく実世界のアプリケーションを構築できます。さらにSDK には組み込みの **トレーシング** が含まれており、エージェント型フローの可視化とデバッグ、評価、さらにはアプリケーション向けモデルのファインチューニング可能です。
## Agents SDK を使う理由
## Agents SDK の利用理由
SDK には 2 つの中核となる設計原則があります
SDK の設計を支える原則は 2 つあります:
1. 使価値があるだけの十分な機能を持ちつつ、素早く学べるよう基本コンポーネントは少数にすること。
2. そのままですぐに優れた動作をしつつ、何が起るかを正確にカスタマイズできること。
1. 使用する価値がある十分な機能を備えつつ、すばやく学べるだけの少数の基本コンポーネントに抑えること。
2. そのままで優れた動作をしつつ、何が起るかを正確にカスタマイズできること。
以下が SDK の主な機能です
SDK の主な機能は次のとおりです:
- **エージェントループ**: ツール呼び出しを処理し、結果を LLM に返し、タスク完了まで継続する組み込みのエージェントループです。
- **Python ファースト**: 新しい抽象化を学ぶ必要なく、組み込みの言語機能を使ってエージェントをオーケストレーションし、連結できます。
- **Agents as tools / ハンドオフ**: 複数エージェント間で作業を調整委任するための強力な仕組みです。
- **ガードレール**: エージェント実行と並行して入力検証と安全性チェックを実行し、チェック不合格時には即座に失敗させます。
- **関数ツール**: 自動スキーマ生成と Pydantic による検証で、任意の Python 関数をツール化できます。
- **MCP サーバーツール呼び出し**: 関数ツールと同様に動作する、組み込みの MCP サーバーツール統合です。
- **セッション**: エージェントループ内で作業コンテキストを維持するための永続メモリレイヤーです。
- **Human in the loop**: エージェント実行全体で人間を関与させるための組み込みメカニズムです。
- **トレーシング**: ワークフローの可視化・デバッグ・監視のための組み込みトレーシングで、OpenAI の評価・ファインチューニング・蒸留ツール群をサポートします。
- **Realtime Agents**: `gpt-realtime-1.5`、自動割り込み検知、コンテキスト管理、ガードレールなどにより、強力な音声エージェントを構築できます。
- **エージェントループ**: ツール呼び出しを処理し、結果を LLM に送り返し、タスク完了するまで継続する組み込みのエージェントループです。
- **Python ファースト**: 新しい抽象化を学ぶ必要なく、組み込みの言語機能を使ってエージェントをオーケストレーションし、連鎖させます。
- **Agents as tools / ハンドオフ**: 複数エージェント間で作業を調整し、委任するための強力な仕組みです。
- **Sandbox エージェント**: マニフェストで定義されたファイル、Sandbox クライアントの選択、再開可能なサンドボックスセッションを備えた、実際の隔離ワークスペース内で専門エージェントを実行します。
- **ガードレール**: エージェント実行と並行して入力検証と安全性チェックを実行し、チェックに通らない場合は即座に失敗として終了します。
- **関数ツール**: スキーマの自動生成と Pydantic によるバリデーションにより、任意の Python 関数をツールに変換します。
- **MCP サーバーのツール呼び出し**: 関数ツールと同じように動作する、組み込みの MCP サーバーツール統合です。
- **セッション**: エージェントループ内で作業コンテキストを維持するための永続的なメモリレイヤーです。
- **ヒューマンインザループ**: エージェント実行の各所に人間を関与させるための組み込みの仕組みです。
- **トレーシング**: ワークフローを可視化、デバッグ、監視するための組み込みのトレーシングで、OpenAI の評価、ファインチューニング、蒸留ツール群をサポートします。
- **Realtime エージェント**: `gpt-realtime-2.1` を使い、自動割り込み検出、コンテキスト管理、ガードレールなどを備えた強力な音声エージェントを構築します。
## Agents SDK と Responses API の選択
SDK は OpenAI モデルに対してデフォルトで Responses API を使用しますが、モデル呼び出しの周りに高レベルのランタイムを追加します。
次の場合は Responses API を直接使用します:
- ループ、ツールのディスパッチ、状態処理を自分で管理したい場合
- ワークフローが短期間で、主にモデルの応答を返すことが目的の場合
次の場合は Agents SDK を使用します:
- ランタイムにターン、ツール実行、ガードレール、ハンドオフ、またはセッションを管理させたい場合
- エージェントが成果物を生成する、または複数の協調したステップにわたって動作する必要がある場合
- 実際のワークスペース、または [Sandbox エージェント](sandbox_agents.md) による再開可能な実行が必要な場合
アプリケーション全体でどちらか一方を選ぶ必要はありません。多くのアプリケーションでは、管理されたワークフローには SDK を使用し、低レベルの処理経路では Responses API を直接呼び出します。
## インストール
@@ -38,7 +56,7 @@ SDK には 2 つの中核となる設計原則があります。
pip install openai-agents
```
## Hello world 例
## Hello world
```python
from agents import Agent, Runner
@@ -53,29 +71,31 @@ print(result.final_output)
# Infinite loop's dance.
```
_これを実行する場合は、`OPENAI_API_KEY` 環境変数を設定してください_
(_これを実行する場合は、 `OPENAI_API_KEY` 環境変数を設定していることを確認してください_)
```bash
export OPENAI_API_KEY=sk-...
```
## 開始地点
## 開始ポイント
- [Quickstart](quickstart.md) で最初のテキストベースエージェントを構築します。
- 次に [Running agents](running_agents.md#choose-a-memory-strategy) で、ターン間で状態をどのように保持するかを決ます。
- handoffs と manager スタイルのオーケストレーションのどちらにするか検討している場合は、[Agent orchestration](multi_agent.md) を参照してください。
- [クイックスタート](quickstart.md) で最初のテキストベースエージェントを構築します。
- 次に[エージェントの実行](running_agents.md#choose-a-memory-strategy) で、ターン間で状態をどのように引き継ぐかを決定します。
- タスクが実際のファイル、リポジトリ、またはエージェントごとに隔離されたワークスペース状態に依存する場合は、[Sandbox エージェントのクイックスタート](sandbox_agents.md) を参照してください。
- ハンドオフとマネージャースタイルのオーケストレーションのどちらにするかを決める場合は、[エージェントオーケストレーション](multi_agent.md) を参照してください。
## パスの選択
やりたい作業は分かっている、どのページ説明があるか分からない場合は、この表を使てください。
実行したい作業は分かっているものの、どのページ説明されているか分からない場合は、この表を使用してください。
| 目 | 開始地点 |
| 目 | 参照先 |
| --- | --- |
| 最初のテキストエージェントを構築し、1 回の完全な実行を確認する | [Quickstart](quickstart.md) |
| 関数ツール、ホストツール、または Agents as tools を追加する | [Tools](tools.md) |
| handoffs と manager スタイルのオーケストレーションのどちらにするか決める | [Agent orchestration](multi_agent.md) |
| ターン間でメモリを保持する | [Running agents](running_agents.md#choose-a-memory-strategy) と [Sessions](sessions/index.md) |
| OpenAI モデル、websocket トランスポート、または非 OpenAI プロバイダーを使う | [Models](models/index.md) |
| 出力、実行項目、中断、再開状態を確認する | [Results](results.md) |
| `gpt-realtime-1.5` で低レイテンシの音声エージェントを構築する | [Realtime agents quickstart](realtime/quickstart.md) と [Realtime transport](realtime/transport.md) |
| speech-to-text / agent / text-to-speech パイプラインを構築する | [Voice pipeline quickstart](voice/quickstart.md) |
| 最初のテキストエージェントを構築し、完全な 1 回の実行を確認する | [クイックスタート](quickstart.md) |
| 関数ツール、OpenAI がホストするツール、または agents as tools を追加する | [ツール](tools.md) |
| 実際の隔離ワークスペース内で、コーディング、レビュー、またはドキュメント処理のエージェントを実行する | [Sandbox エージェントのクイックスタート](sandbox_agents.md) and [Sandbox クライアント](sandbox/clients.md) |
| ハンドオフとマネージャースタイルのオーケストレーションのどちらを使うか決める | [エージェントオーケストレーション](multi_agent.md) |
| ターン間でメモリを保持する | [エージェントの実行](running_agents.md#choose-a-memory-strategy) and [セッション](sessions/index.md) |
| OpenAI モデル、WebSocket トランスポート、または OpenAI 以外のプロバイダーを使用する | [モデル](models/index.md) |
| 出力、実行アイテム、割り込み、再開状態を確認する | [実行結果](results.md) |
| `gpt-realtime-2.1` を使って低レイテンシの音声エージェントを構築する | [Realtime エージェントのクイックスタート](realtime/quickstart.md) and [Realtime トランスポート](realtime/transport.md) |
| 音声認識 / エージェント / 音声合成のパイプラインを構築する | [音声パイプラインのクイックスタート](voice/quickstart.md) |
+105 -94
View File
@@ -4,28 +4,31 @@ search:
---
# Model context protocol (MCP)
[Model context protocol](https://modelcontextprotocol.io/introduction) (MCP) は、アプリケーションが言語モデルにツールやコンテキストを公開する方法を標準化します。公式ドキュメントより:
[Model context protocol](https://modelcontextprotocol.io/introduction) (MCP) は、アプリケーションがツールや
コンテキストを言語モデルに公開する方法を標準化します。公式ドキュメントより:
> MCP は、アプリケーションが LLM にコンテキストを提供する方法を標準化するオープンプロトコルです。MCP は AI アプリケーション向けの USB-C ポートのようなものだと考えてください。USB-C がデバイスをさまざまな周辺機器やアクセサリーに接続するための標準化された方法を提供するのと同様に、MCP は AI モデルを異なるデータソースやツールに接続するための標準化された方法を提供します。
> MCP は、アプリケーションが LLM にコンテキストを提供する方法を標準化するオープンプロトコルです。MCP は、AI
> アプリケーションにおける USB-C ポートのようなものだと考えてください。USB-C がデバイスをさまざまな周辺機器やアクセサリに接続する標準化された方法を提供するのと同様に、MCP
> は AI モデルをさまざまなデータソースやツールに接続する標準化された方法を提供します。
Agents Python SDK は複数の MCP トランスポートを理解します。これにより、既存の MCP サーバーを再利用したり、独自に構築してファイルシステム、 HTTP 、またはコネクタをバックエンドとするツールをエージェントに公開したりできます。
Agents Python SDK は複数の MCP トランスポートに対応しています。これにより、既存の MCP サーバーを再利用したり、独自に構築してファイルシステム、HTTP、またはコネクタをバックエンドとするツールをエージェントに公開できます。
## MCP 統合の選択
MCP サーバーをエージェントに接続する前に、ツール呼び出しをどこで実行するか、到達可能なトランスポートはどれかを決めてください。以下のマトリクスは、 Python SDK がサポートする選択肢を要約したものです。
MCP サーバーをエージェントに組み込む前に、ツール呼び出しをどこで実行すべきか、どのトランスポートに到達できるかを決めてください。次の表は、Python SDK がサポートする選択肢の概要です。
| 必要なもの | 推奨オプション |
| 必要なこと | 推奨オプション |
| ------------------------------------------------------------------------------------ | ----------------------------------------------------- |
| モデルの代わりに OpenAI の Responses API から公開到達可能な MCP サーバーを呼び出す | [`HostedMCPTool`][agents.tool.HostedMCPTool] による **Hosted MCP server tools** |
| ローカルまたはリモートで実行している Streamable HTTP サーバーに接続する | [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] による **Streamable HTTP MCP servers** |
| Server-Sent Events を使う HTTP を実装しサーバーと通信する | [`MCPServerSse`][agents.mcp.server.MCPServerSse] による **HTTP with SSE MCP servers** |
| ローカルプロセスを起動し stdin/stdout 経由で通信する | [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] による **stdio MCP servers** |
| OpenAI の Responses API に、モデルに代わって公開到達可能な MCP サーバーを呼び出させる| **ホスト型 MCP サーバーツール** [`HostedMCPTool`][agents.tool.HostedMCPTool] 経由) |
| ローカルまたはリモートで実行している Streamable HTTP サーバーに接続する | **Streamable HTTP MCP サーバー** [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] 経由) |
| Server-Sent Events を用いた HTTP を実装しているサーバーと通信する | **SSE を用いた HTTP MCP サーバー** [`MCPServerSse`][agents.mcp.server.MCPServerSse] 経由) |
| ローカルプロセスを起動しstdin/stdout 経由で通信する | **stdio MCP サーバー** [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] 経由) |
のセクションでは、各オプション、設定方法、どのトランスポートを優先すべきかを説明します。
のセクションでは、各オプション、その設定方法、あるトランスポートを別のトランスポートより優先すべきタイミングについて説明します。
## エージェントレベルの MCP 設定
トランスポートの選択に加えて、 `Agent.mcp_config` を設定して MCP ツールの準備方法を調整できます。
トランスポートの選択に加えて、`Agent.mcp_config` を設定することで MCP ツールの準備方法を調整できます。
```python
from agents import Agent
@@ -39,35 +42,38 @@ agent = Agent(
# If None, MCP tool failures are raised as exceptions instead of
# returning model-visible error text.
"failure_error_function": None,
# Prefix local MCP tool names with their server name.
"include_server_in_tool_names": True,
},
)
```
:
注:
- `convert_schemas_to_strict` はベストエフォートです。スキーマを変換できない場合は元のスキーマが使れます。
- `failure_error_function` MCP ツール呼び出し失敗をモデルどのように提示するかを制御します。
- `failure_error_function` が未設定の場合、 SDK はデフォルトのツールエラーフォーマッターを使ます。
- サーバーレベルの `failure_error_function` は、そのサーバーに対し`Agent.mcp_config["failure_error_function"]` を上書きします。
- `convert_schemas_to_strict` はベストエフォートです。スキーマを変換できない場合は元のスキーマが使用されます。
- `failure_error_function`MCP ツール呼び出し失敗をモデルどのように提示するかを制御します。
- `failure_error_function` が未設定の場合、SDK はデフォルトのツールエラーフォーマッターを使用します。
- サーバーレベルの `failure_error_function` は、そのサーバーについ`Agent.mcp_config["failure_error_function"]` を上書きします。
- `include_server_in_tool_names` はオプトインです。有効にすると、各ローカル MCP ツールは、決定論的なサーバー接頭辞付きの名前でモデルに公開されます。これにより、複数の MCP サーバーが同じ名前のツールを公開する場合の衝突を避けやすくなります。生成される名前は ASCII セーフで、関数ツール名の長さ制限内に収まり、同じエージェント上の既存のローカル関数ツール名および有効化されたハンドオフ名を避けます。それでも SDK は元のサーバー上で元の MCP ツール名を呼び出します。
## トランスポート間の共通パターン
## トランスポート共通パターン
トランスポートを選んだ後、ほとんどの統合で同じ追加判断が必要です:
トランスポートを選択した後、多くの統合で同じ追加判断が必要になります。
- ツールの一部だけを公開する方法 ([Tool filtering](#tool-filtering))
- サーバーが再利用可能なプロンプトも提供するかどうか ([Prompts](#prompts))
- `list_tools()` をキャッシュすべきかどうか ([Caching](#caching))
- MCP アクティビティがトレースにど表示されるか ([Tracing](#tracing))
- ツールのサブセットのみを公開する方法([ツールフィルタリング](#tool-filtering)
- サーバーが再利用可能なプロンプトも提供するかどうか[プロンプト](#prompts)
- `list_tools()` をキャッシュすべきかどうか[キャッシュ](#caching)
- MCP アクティビティがトレースにどのように表示されるか[トレーシング](#tracing)
ローカル MCP サーバー (`MCPServerStdio``MCPServerSse``MCPServerStreamableHttp`) では、承認ポリシーと呼び出しごとの `_meta` ペイロードも共通概念です。 Streamable HTTP セクション最も完全なコード例を示しており、同じパターン他のローカルトランスポートにも適用されます。
ローカル MCP サーバー`MCPServerStdio``MCPServerSse``MCPServerStreamableHttp`では、承認ポリシーと呼び出しごとの `_meta` ペイロードも共通概念です。Streamable HTTP セクションでは最も完全な例を示しており、同じパターン他のローカルトランスポートにも適用されます。
## 1. Hosted MCP server tools
## 1. ホスト型 MCP サーバーツール
Hosted ツールは、ツールの往復全体を OpenAI のインフラに委ねます。コード側でツールを列挙・呼び出す代わりに、[`HostedMCPTool`][agents.tool.HostedMCPTool] がサーバーラベル(および任意のコネクタメタデータ)を Responses API に転送します。モデルはリモートサーバーのツールを列挙し、 Python プロセスへの追加コールバックなしで実行します。 Hosted ツールは現在、 Responses API の hosted MCP 統合をサポートする OpenAI モデルで動作します。
ホスト型ツールは、ツールのラウンドトリップ全体を OpenAI のインフラに委ねます。ツールの一覧取得と呼び出しをコード側で行う代わりに、[`HostedMCPTool`][agents.tool.HostedMCPTool] がサーバーラベル(および任意のコネクタメタデータ)を Responses API に転送します。モデルはリモートサーバーのツールを一覧表示し、Python プロセスへの追加コールバックなしにそれらを呼び出します。現在、ホスト型ツールは Responses API のホスト型 MCP 統合をサポートする OpenAI モデルで動作します。
### 基本の Hosted MCP ツール
### 基本的なホスト型 MCP ツール
エージェントの `tools` リストに [`HostedMCPTool`][agents.tool.HostedMCPTool] を追加して Hosted ツールを作成します。 `tool_config` 辞書は REST API に送る JSON を反映します:
エージェントの `tools` リストに [`HostedMCPTool`][agents.tool.HostedMCPTool] を追加してホスト型ツールを作成します。`tool_config` 辞書は REST API に送信する JSON と同じ構造です:
```python
import asyncio
@@ -77,31 +83,36 @@ from agents import Agent, HostedMCPTool, Runner
async def main() -> None:
agent = Agent(
name="Assistant",
instructions="Use the DeepWiki hosted MCP server to inspect openai/openai-agents-python.",
tools=[
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "gitmcp",
"server_url": "https://gitmcp.io/openai/codex",
"server_label": "deepwiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"require_approval": "never",
}
)
],
)
result = await Runner.run(agent, "Which language is this repository written in?")
result = await Runner.run(
agent,
"Which language is the repository openai/openai-agents-python written in?",
)
print(result.final_output)
asyncio.run(main())
```
Hosted サーバーはツールを自動公開するため、 `mcp_servers` に追加する必要はありません。
ホスト型サーバーはツールを自動的に公開します。`mcp_servers` に追加する必要はありません。
Hosted ツール検索で hosted MCP サーバーを遅延読み込みたい場合は、 `tool_config["defer_loading"] = True` を設定し、エージェントに [`ToolSearchTool`][agents.tool.ToolSearchTool] を追加してください。これは OpenAI Responses モデルでのみサポートされます。完全なツール検索の設定と制約は [Tools](tools.md#hosted-tool-search) を参照してください。
ホスト型ツール検索にホスト型 MCP サーバーを遅延読み込みさせたい場合は、`tool_config["defer_loading"] = True` を設定し、エージェントに [`ToolSearchTool`][agents.tool.ToolSearchTool] を追加します。これは OpenAI Responses モデルでのみサポートされます。ツール検索の完全な設定と制約については、[ツール](tools.md#hosted-tool-search) を参照してください。
### Hosted MCP 結果のストリーミング
### ホスト型 MCP 結果のストリーミング
Hosted ツールは、関数ツールとまったく同じ方法で結果のストリーミングをサポートします。 `Runner.run_streamed` を使うと、モデルがまだ処理中でも増分 MCP 出力を消費できます:
ホスト型ツールは、関数ツールとまったく同じ方法で結果のストリーミングをサポートします。モデルがまだ処理中でも、`Runner.run_streamed` を使用して
増分的な MCP 出力を受け取れます:
```python
result = Runner.run_streamed(agent, "Summarise this repository's top languages")
@@ -113,12 +124,12 @@ print(result.final_output)
### 任意の承認フロー
サーバーが機密操作を実行可能な場合、各ツール実行前に人またはプログラムによる承認を要求できます。 `tool_config` `require_approval` 、単一ポリシー (`"always"``"never"`) またはツール名からポリシーへの辞書を設定します。 Python で判断するには `on_approval_request` コールバックを提供します。
サーバーが機密性の高い操作を実行できる場合、各ツール実行前に人またはプログラムによる承認を必須にできます。`tool_config` `require_approval` 、単一ポリシー`"always"``"never"`またはツール名ポリシーにマッピングする辞書として設定します。Python で判断するには`on_approval_request` コールバックを指定します。
```python
from agents import MCPToolApprovalFunctionResult, MCPToolApprovalRequest
SAFE_TOOLS = {"read_project_metadata"}
SAFE_TOOLS = {"read_wiki_structure", "read_wiki_contents", "ask_question"}
def approve_tool(request: MCPToolApprovalRequest) -> MCPToolApprovalFunctionResult:
if request.data.name in SAFE_TOOLS:
@@ -131,8 +142,8 @@ agent = Agent(
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "gitmcp",
"server_url": "https://gitmcp.io/openai/codex",
"server_label": "deepwiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"require_approval": "always",
},
on_approval_request=approve_tool,
@@ -141,11 +152,11 @@ agent = Agent(
)
```
このコールバックは同期・非同期のどちらでもよく、モデルが実行継続ため承認データを必要とするたびに呼び出されます。
このコールバックは同期または非同期にでき、モデルが実行継続するため承認データを必要とするたびに呼び出されます。
### コネクタをバックエンドとする Hosted サーバー
### コネクター対応のホスト型サーバー
Hosted MCP は OpenAI コネクタもサポートします。 `server_url` を指定する代わりに、 `connector_id` とアクセストークンをします。 Responses API が認証を処理し、 hosted サーバーがコネクタのツールを公開します。
ホスト型 MCP は OpenAI コネクターにも対応しています。`server_url` を指定する代わりに、`connector_id` とアクセストークンを指定します。Responses API が認証を処理し、ホスト型サーバーがコネクタのツールを公開します。
```python
import os
@@ -161,11 +172,11 @@ HostedMCPTool(
)
```
ストリーミング、承認、コネクタを含む完全動作する Hosted ツールのサンプルは、[`examples/hosted_mcp`](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) にあります。
完全に動作するホスト型ツールのサンプル(ストリーミング、承認、コネクタを含む)は [`examples/hosted_mcp`](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) にあります。
## 2. Streamable HTTP MCP servers
## 2. Streamable HTTP MCP サーバー
ネットワーク接続を自分で管理したい場合は、[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] を使用します。 Streamable HTTP サーバーは、トランスポートを制御したい場合や、低遅延を保ちながら自インフラ内でサーバーを実行したい場合に最適です。
ネットワーク接続を自分で管理したい場合は、[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] を使用します。Streamable HTTP サーバーは、トランスポートを制御したい場合や、レイテンシを低く保ちながら自分のインフラ内でサーバーを実行したい場合に最適です。
```python
import asyncio
@@ -200,27 +211,26 @@ async def main() -> None:
asyncio.run(main())
```
コンストラクターは追加オプションを受け取ります:
コンストラクターは追加オプションを受け取ります
- `client_session_timeout_seconds` は HTTP 読み取りタイムアウトを制御します。
- `use_structured_content`テキスト出力より `tool_result.structured_content` を優先するかを切り替えます。
- `max_retry_attempts``retry_backoff_seconds_base` `list_tools()``call_tool()` 自動リトライを追加します。
- `tool_filter` はツールの一部だけを公開できます([Tool filtering](#tool-filtering) 参照)。
- `require_approval` はローカル MCP ツールで human-in-the-loop 承認ポリシーを有効します。
- `failure_error_function` はモデルに見える MCP ツール失敗メッセージをカスタマイズします。代わりにエラーを送出したい場合は `None` 設定します。
- `tool_meta_resolver` `call_tool()` 前に呼び出しごとの MCP `_meta` ペイロードを注入します。
- `client_session_timeout_seconds` は HTTP 読み取りタイムアウトを制御します。
- `use_structured_content``tool_result.structured_content`テキスト出力より優先するかどうかを切り替えます。
- `max_retry_attempts``retry_backoff_seconds_base``list_tools()``call_tool()` 自動リトライを追加します。
- `tool_filter`ツールのサブセットのみを公開できるようにします([ツールフィルタリング](#tool-filtering) 参照)。
- `require_approval`ローカル MCP ツールでヒューマンインザループの承認ポリシーを有効します。
- `failure_error_function`モデルに表示される MCP ツール失敗メッセージをカスタマイズします。`None` 設定すると、代わりにエラーを送出します。
- `tool_meta_resolver`呼び出しごとの MCP `_meta` ペイロードを `call_tool()` の前に注入します。
### ローカル MCP サーバーの承認ポリシー
`MCPServerStdio``MCPServerSse``MCPServerStreamableHttp`すべて `require_approval` を受け付けます。
`MCPServerStdio``MCPServerSse``MCPServerStreamableHttp`いずれも `require_approval` を受け取ります。
サポートされる形式:
- すべてのツールに対する `"always"` または `"never"`
- `True` / `False` always/never と同等)。
- ツールごとのマップ。例: `{"delete_file": "always", "read_file": "never"}`
- グループ化オブジェクト:
`{"always": {"tool_names": [...]}, "never": {"tool_names": [...]}}`
- すべてのツールに対する `"always"` または `"never"`
- `True` / `False`always/never と同等)。
- ツールごとのマップ。例: `{"delete_file": "always", "read_file": "never"}`
- グループ化されたオブジェクト: `{"always": {"tool_names": [...]}, "never": {"tool_names": [...]}}`
```python
async with MCPServerStreamableHttp(
@@ -231,11 +241,11 @@ async with MCPServerStreamableHttp(
...
```
完全な一時停止/再開フローは、 [Human-in-the-loop](human_in_the_loop.md) と `examples/mcp/get_all_mcp_tools_example/main.py` を参照してください。
完全な一時停止 / 再開フローについては、[ヒューマンインザループ](human_in_the_loop.md) と `examples/mcp/get_all_mcp_tools_example/main.py` を参照してください。
### `tool_meta_resolver` による呼び出しごとのメタデータ
MCP サーバーが `_meta` リクエストメタデータ(例: テナント ID やトレースコンテキスト)を必要とする場合は `tool_meta_resolver` を使ます。下の例は、 `Runner.run(...)``context` として `dict` を渡すことを前提しています。
MCP サーバーが `_meta` リクエストメタデータ(たとえばテナント ID やトレースコンテキスト)を期待する場合は`tool_meta_resolver` を使用します。下の例は、`Runner.run(...)``context` として `dict` を渡すことを前提しています。
```python
from agents.mcp import MCPServerStreamableHttp, MCPToolMetaContext
@@ -256,19 +266,19 @@ server = MCPServerStreamableHttp(
)
```
実行コンテキストが Pydantic モデル、 dataclass 、またはカスタムクラスの場合は、代わりに属性アクセスでテナント ID を読み取ってください。
実行コンテキストが Pydantic モデル、データクラス、またはカスタムクラスの場合は、属性アクセスでテナント ID を読み取ってください。
### MCP ツール出力: テキストと画像
MCP ツールが画像コンテンツを返す場合、 SDK はそれを自動的に画像ツール出力エントリにマップします。テキスト/画像混在レスポンスは出力項目のリストとして転送されるため、エージェントは通常の関数ツールからの画像出力と同じ方法で MCP 画像結果を処理できます。
MCP ツールが画像コンテンツを返すと、SDK はそれを画像ツール出力エントリーに自動的にマッピングします。テキスト / 画像混在レスポンスは出力項目のリストとして転送されるため、エージェントは通常の関数ツールからの画像出力を扱うのと同じ方法で MCP 画像結果を扱えます。
## 3. HTTP with SSE MCP servers
## 3. SSE を用いた HTTP MCP サーバー
!!! warning
MCP プロジェクトは Server-Sent Events トランスポート非推奨にしています。新規統合では Streamable HTTP または stdio を優先し、 SSE はレガシーサーバーのみしてください。
MCP プロジェクトは Server-Sent Events トランスポート非推奨になりました。新しい統合では Streamable HTTP または stdio を優先し、SSE はレガシーサーバーのみ使用してください。
MCP サーバーが HTTP with SSE トランスポートを実装している場合は、[`MCPServerSse`][agents.mcp.server.MCPServerSse] をインスタンス化します。トランスポート以外API は Streamable HTTP サーバーと同一です。
MCP サーバーが SSE を用いた HTTP トランスポートを実装している場合は、[`MCPServerSse`][agents.mcp.server.MCPServerSse] をインスタンス化します。トランスポート以外は、API は Streamable HTTP サーバーと同一です。
```python
@@ -295,9 +305,9 @@ async with MCPServerSse(
print(result.final_output)
```
## 4. stdio MCP servers
## 4. stdio MCP サーバー
ローカルサブプロセスとして実行される MCP サーバーには、 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] を使ます。 SDK はプロセスを起動し、パイプを開いたまま維持し、コンテキストマネージャー終了時に自動で閉じます。このオプションは、素早い概念実証や、サーバーがコマンドラインエントリポイントしか公開していない場合に有用です。
ローカルサブプロセスとして実行される MCP サーバーには、[`MCPServerStdio`][agents.mcp.server.MCPServerStdio] を使用します。SDK はプロセスを起動し、パイプを開いたままし、コンテキストマネージャーを抜けると自動的に閉じます。このオプションは、簡単な概念実証や、サーバーがコマンドラインエントリポイントのみを公開する場合に役立ちます。
```python
from pathlib import Path
@@ -325,7 +335,7 @@ async with MCPServerStdio(
## 5. MCP サーバーマネージャー
複数の MCP サーバーがある場合は、 `MCPServerManager` を使て事前に接続し、接続済みサブセットをエージェントに公開します。コンストラクターオプションと再接続動作[MCPServerManager API reference](ref/mcp/manager.md) を参照してください。
複数の MCP サーバーがある場合は、`MCPServerManager` を使用して事前に接続し、接続済みサブセットをエージェントに公開します。コンストラクターオプションと再接続動作については、[MCPServerManager API リファレンス](ref/mcp/manager.md) を参照してください。
```python
from agents import Agent, Runner
@@ -346,25 +356,25 @@ async with MCPServerManager(servers) as manager:
print(result.final_output)
```
主な動:
主な動:
- `active_servers` `drop_failed_servers=True` (デフォルト)時に接続成功したサーバーのみを含みます。
- `active_servers` には、`drop_failed_servers=True`(デフォルト)の場合、正常に接続されたサーバーのみが含まれます。
- 失敗は `failed_servers``errors` で追跡されます。
- 最初の接続失敗で例外を発生させるには `strict=True` を設定します。
- 失敗サーバーのみ再試行するには `reconnect(failed_only=True)` 、全サーバーを再起動するには `reconnect(failed_only=False)` を呼びます。
- ライフサイクル動作を調整するには `connect_timeout_seconds``cleanup_timeout_seconds``connect_in_parallel` を使ます。
- `strict=True` を設定すると、最初の接続失敗時にエラーを送出します。
- `reconnect(failed_only=True)` を呼び出すと失敗したサーバーを再試行し、`reconnect(failed_only=False)` を呼び出すとすべてのサーバーを再起動します。
- `connect_timeout_seconds``cleanup_timeout_seconds``connect_in_parallel` を使用してライフサイクル動作を調整します。
## 共通サーバー機能
## 共通サーバー機能
以下のセクションは MCP サーバートランスポート全体に適用されます(正確な API 表面はサーバークラスに依存します)。
以下のセクションは MCP サーバートランスポート全体に適用されます(正確な API の範囲はサーバークラスによって異なります)。
## Tool filtering
## ツールフィルタリング
各 MCP サーバーはツールフィルターをサポートしており、エージェントに必要な関数だけを公開できます。フィルタリングは構築時または実行ごとに動的に行ます。
各 MCP サーバーはツールフィルターに対応しているため、エージェントに必要な関数だけを公開できます。フィルタリングは構築時に行うことも、実行ごとに動的に行うこともできます。
### 静的ツールフィルタリング
### 静的ツールフィルタリング
シンプルな許可/ブロックリストを設定するには [`create_static_tool_filter`][agents.mcp.create_static_tool_filter] を使ます:
[`create_static_tool_filter`][agents.mcp.create_static_tool_filter] を使用して、シンプルな許可 / ブロックリストを設定します:
```python
from pathlib import Path
@@ -382,11 +392,11 @@ filesystem_server = MCPServerStdio(
)
```
`allowed_tool_names``blocked_tool_names` の両方が与えられた場合、 SDK はまず許可リストを適用し、その残り集合からブロック対象ツールを除します。
`allowed_tool_names``blocked_tool_names` の両方が指定された場合、SDK はまず許可リストを適用し、その後、残ったセットからブロックされたツールを除します。
### 動的ツールフィルタリング
### 動的ツールフィルタリング
より高度なロジックには [`ToolFilterContext`][agents.mcp.ToolFilterContext] を受け取る callable を渡します。 callable は同期・非同期のいずれでもよく、ツールを公開すべき場合に `True` を返します。
より高度なロジックには[`ToolFilterContext`][agents.mcp.ToolFilterContext] を受け取るコール可能オブジェクトを渡します。このコール可能オブジェクトは同期または非同期にでき、ツールを公開すべき場合に `True` を返します。
```python
from pathlib import Path
@@ -410,14 +420,15 @@ async with MCPServerStdio(
...
```
フィルターコンテキストは、アクティブな `run_context` 、ツールを要求`agent` 、および `server_name` を公開します。
フィルターコンテキストは、アクティブな `run_context`、ツールを要求してい`agent`、および `server_name` を公開します。
## Prompts
## プロンプト
MCP サーバーは、エージェント指示を動的生成するプロンプトも提供できます。プロンプト対応サーバーは次の 2 つのメソッドを公開します:
MCP サーバーは、エージェント指示を動的生成するプロンプトも提供できます。プロンプト対応するサーバーは 2 つの
メソッドを公開します:
- `list_prompts()` は利用可能なプロンプトテンプレートを列挙します。
- `get_prompt(name, arguments)` は具体的なプロンプトを取得します(必要に応じてパラメーター付き)
- `get_prompt(name, arguments)` は具体的なプロンプトを取得します。任意でパラメーターを指定できます
```python
from agents import Agent
@@ -435,21 +446,21 @@ agent = Agent(
)
```
## Caching
## キャッシュ
エージェント実行各 MCP サーバーで `list_tools()` 呼びます。リモートサーバーは目立つレイテンシを生む可能性があるため、すべての MCP サーバークラスは `cache_tools_list` オプションを公開しています。ツール定義が頻繁に変わらないと確信できる場合にのみ `True` に設定してください。後で最新リストを強制したい場合は、サーバーインスタンスで `invalidate_tools_cache()` を呼びます。
エージェント実行するたびに、各 MCP サーバーで `list_tools()` 呼び出されます。リモートサーバーは目に見えるレイテンシが発生する可能性があるため、すべての MCP サーバークラスは `cache_tools_list` オプションを公開しています。ツール定義が頻繁に変更されないと確信できる場合にのみ`True` に設定してください。後で最新リストを強制的に取得するには、サーバーインスタンスで `invalidate_tools_cache()` を呼び出します。
## Tracing
## トレーシング
[Tracing](./tracing.md) は、以下を含む MCP アクティビティを自動で記録します:
[トレーシング](./tracing.md) は、を含む MCP アクティビティを自動的にキャプチャします
1. ツール一覧取得のための MCP サーバー呼び出し。
1. ツール一覧表示するための MCP サーバーへの呼び出し。
2. ツール呼び出し上の MCP 関連情報。
![MCP Tracing Screenshot](../assets/images/mcp-tracing.jpg)
![MCP トレーシングのスクリーンショット](../assets/images/mcp-tracing.jpg)
## 参考情報
- [Model Context Protocol](https://modelcontextprotocol.io/) 仕様と設計ガイド。
- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) 実行可能な stdio 、 SSE 、 Streamable HTTP サンプル。
- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) 承認とコネクタを含む完全な hosted MCP デモ。
- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) 実行可能な stdio、SSE、Streamable HTTP サンプル。
- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) 承認とコネクタを含む完全なホスト型 MCP デモ。
+367 -153
View File
@@ -4,42 +4,43 @@ search:
---
# モデル
Agents SDK には、OpenAI モデルをすぐに使える形で 2 つの方式でサポートしています。
Agents SDKには、すぐに利用できる OpenAIモデルのサポートが 2 種類用意されています。
- **推奨**: [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]。新しい [Responses API](https://platform.openai.com/docs/api-reference/responses) を使て OpenAI API を呼び出します。
- [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]。 [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) を使って OpenAI API を呼び出します
- **推奨**: 新しい [Responses API](https://platform.openai.com/docs/api-reference/responses) を使用して OpenAI API を呼び出す [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]
- [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) を使用して OpenAI API を呼び出す [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]。
## モデル設定の選択
ご利用の構成に合う最もシンプルな経路から始めてください。
設定に適した最もシンプルな方法から始めてください。
| 目的 | 推奨経路 | 詳細 |
| 実現したいこと | 推奨される方法 | 詳細 |
| --- | --- | --- |
| OpenAI モデルのみを使う | デフォルトの OpenAI provider と Responses モデル経路を使う | [OpenAI モデル](#openai-models) |
| websocket 転送で OpenAI Responses API を使 | Responses モデル経路を維持し、websocket 転送を有効する | [Responses WebSocket 転送](#responses-websocket-transport) |
| 1 つの non-OpenAI provider を使う | 組み込みの provider 統合ポイントから始める | [non-OpenAI モデル](#non-openai-models) |
| エージェント間でモデルや provider を混在させる | 実行単位またはエージェント単位で provider を選び、機能差を確認する | [1 つのワークフロー内でのモデル混在](#mixing-models-in-one-workflow) および [provider 間でのモデル混在](#mixing-models-across-providers) |
| OpenAI Responses の高度なリクエスト設定を調整する | OpenAI Responses 経路で `ModelSettings` を使う | [高度な OpenAI Responses 設定](#advanced-openai-responses-settings) |
| non-OpenAI Chat Completions provider に LiteLLM を使う | LiteLLM を beta のフォールバックとして扱う | [LiteLLM](#litellm) |
| OpenAIモデルのみを使用する | Responses モデルパスでデフォルトの OpenAIプロバイダーを使用する | [OpenAIモデル](#openai-models) |
| WebSocket トランスポート経由で OpenAI Responses API を使用する | Responses モデルパスを維持し、WebSocket トランスポートを有効する | [Responses WebSocket トランスポート](#responses-websocket-transport) |
| OpenAIがホストするサブエージェントを使用する | 試験的なホスト型マルチエージェントモデルを使用する | [ホスト型マルチエージェント](#hosted-multi-agent-experimental) |
| OpenAI以外のプロバイダーを 1 つ使用する | 組み込みのプロバイダー統合ポイントから始める | [OpenAI以外のモデル](#non-openai-models) |
| エージェント間でモデルまたはプロバイダーを組み合わせる | 実行ごと、またはエージェントごとにプロバイダーを選択し、機能の違いを確認する | [単一ワークフローでのモデルの組み合わせ](#mixing-models-in-one-workflow)および[プロバイダー間でのモデルの組み合わせ](#mixing-models-across-providers) |
| OpenAI Responses の高度なリクエスト設定を調整する | OpenAI Responses パスで `ModelSettings` を使用する | [OpenAI Responses の高度な設定](#advanced-openai-responses-settings) |
| OpenAI以外のプロバイダー、または複数プロバイダーのルーティングにサードパーティ製アダプターを使用する | サポートされているベータ版アダプターを比較し、リリース予定のプロバイダーパスを検証する | [サードパーティ製アダプター](#third-party-adapters) |
## OpenAI モデル
## OpenAIモデル
ほとんどの OpenAI 専用アプリでは、デフォルトの OpenAI provider と文字列のモデル名を使、Responses モデル経路を維持する方法を推奨します。
OpenAIのみを使用するほとんどのアプリでは、デフォルトの OpenAIプロバイダーで文字列のモデル名を使用し、Responses モデルパスを維持する方法を推奨します。
`Agent` 初期化時にモデルを指定しない場合、デフォルトモデルが使れます。現在のデフォルトは互換性と低遅延のため [`gpt-4.1`](https://developers.openai.com/api/docs/models/gpt-4.1) です。利用可能であれば、明示的な `model_settings` を維持しつつ、より高品質な [`gpt-5.4`](https://developers.openai.com/api/docs/models/gpt-5.4) をエージェントに設定することを推奨します。
`Agent` 初期化時にモデルを指定しない場合、デフォルトモデルが使用されます。現在のデフォルトは、低レイテンシーのエージェントワークフロー向けに `reasoning.effort="none"``verbosity="low"` を設定した [`gpt-5.4-mini`](https://developers.openai.com/api/docs/models/gpt-5.4-mini) です。利用できる場合は、明示的な `model_settings` を維持しながら、より高品質を得るためにエージェントを `gpt-5.6-sol` に設定することを推奨します。
[`gpt-5.4`](https://developers.openai.com/api/docs/models/gpt-5.4) のような他モデルに切り替えるには、エージェントを設定する方法 2 つあります。
`gpt-5.6-sol` などの別のモデルに切り替える場合、エージェントを設定する方法 2 つあります。
### デフォルトモデル
まず、カスタムモデルを設定しないすべてのエージェントで特定モデルを一貫して使いたい場合は、エージェント実行前に `OPENAI_DEFAULT_MODEL` 環境変数を設定します。
まず、カスタムモデルを設定していないすべてのエージェントで特定モデルを一貫して使用するには、エージェント実行する前に `OPENAI_DEFAULT_MODEL` 環境変数を設定します。
```bash
export OPENAI_DEFAULT_MODEL=gpt-5.4
export OPENAI_DEFAULT_MODEL=gpt-5.6-sol
python3 my_awesome_agent.py
```
次に、`RunConfig` で実行ごとのデフォルトモデルを設定できます。エージェントにモデルを設定しなければ、この実行のモデルが使れます。
次に、`RunConfig` を使用して実行のデフォルトモデルを設定できます。エージェントにモデルを設定していない場合、この実行のモデルが使用されます。
```python
from agents import Agent, RunConfig, Runner
@@ -52,13 +53,13 @@ agent = Agent(
result = await Runner.run(
agent,
"Hello",
run_config=RunConfig(model="gpt-5.4"),
run_config=RunConfig(model="gpt-5.6-sol"),
)
```
#### GPT-5 モデル
この方法で [`gpt-5.4`](https://developers.openai.com/api/docs/models/gpt-5.4) のような GPT-5 モデルを使う場合、SDK はデフォルトの `ModelSettings` を適用します。多くのユースケース最適に動く設定が使れます。デフォルトモデルの推論 effort を調整するには、独自の `ModelSettings` を渡します。
この方法で `gpt-5.6-sol` などの GPT-5 モデルを使用すると、SDK はデフォルトの `ModelSettings` を適用します。ほとんどのユースケース最適設定が使用されます。デフォルトモデルの推論エフォートを調整するには、独自の `ModelSettings` を渡します。
```python
from openai.types.shared import Reasoning
@@ -67,42 +68,65 @@ from agents import Agent, ModelSettings
my_agent = Agent(
name="My Agent",
instructions="You're a helpful agent.",
# If OPENAI_DEFAULT_MODEL=gpt-5.4 is set, passing only model_settings works.
# If OPENAI_DEFAULT_MODEL=gpt-5.6-sol is set, passing only model_settings works.
# It's also fine to pass a GPT-5 model name explicitly:
model="gpt-5.4",
model="gpt-5.6-sol",
model_settings=ModelSettings(reasoning=Reasoning(effort="high"), verbosity="low")
)
```
低遅延のためには、`gpt-5.4` `reasoning.effort="none"` を使ことを推奨します。gpt-4.1 ファミリー( mini / nano を含む)も、対話型エージェントアプリ構築において有力な選択肢です。
レイテンシーを低減するには、GPT-5 モデル`reasoning.effort="none"` を使用することを推奨します。
#### ComputerTool モデル選択
GPT-5.6 は、既存の `reasoning` 設定を通じて、推論モード、永続化された推論コンテキスト、および `"max"` エフォートレベルもサポートします。これらの制御は Responses API パスで利用できます。
エージェントに [`ComputerTool`][agents.tool.ComputerTool] が含まれる場合、実際の Responses リクエストで有効なモデルによって、SDK が送信する computer-tool ペイロードが決まります。明示的な `gpt-5.4` リクエストでは GA の組み込み `computer` ツールを使い、明示的な `computer-use-preview` リクエストでは従来の `computer_use_preview` ペイロードを維持します。
```python
from openai.types.shared import Reasoning
from agents import Agent, ModelSettings
主な例外は prompt 管理型呼び出しです。prompt テンプレートがモデルを所有し、SDK がリクエストから `model` を省略する場合、SDK は prompt がどのモデルに固定されているかを推測しないため、preview 互換の computer ペイロードをデフォルトで使います。このフローで GA 経路を維持するには、リクエストで `model="gpt-5.4"` を明示するか、`ModelSettings(tool_choice="computer")` または `ModelSettings(tool_choice="computer_use")` で GA セレクターを強制してください。
agent = Agent(
name="Deep research agent",
model="gpt-5.6-sol",
model_settings=ModelSettings(
reasoning=Reasoning(
mode="pro",
effort="max",
context="all_turns",
),
),
)
```
[`ComputerTool`][agents.tool.ComputerTool] が登録されている場合、`tool_choice="computer"``"computer_use"``"computer_use_preview"` は、有効なリクエストモデルに一致する組み込みセレクターに正規化されます。`ComputerTool` が登録されていない場合、これらの文字列は通常の関数名として振る舞い続けます。
`reasoning.mode``reasoning.context` は Responses 専用の設定です。Chat Completions では `reasoning.effort` のみが使用され、サポートされるエフォートレベルはモデルと API サーフェスによって異なります。GPT-5.6 の `"max"` エフォートには Responses API を使用してください。Chat Completions アダプターは警告を出してモードとコンテキストを無視します。その警告をエラーにするには、OpenAIプロバイダーで `strict_feature_validation=True` を設定します。
preview 互換リクエストでは `environment` と表示寸法を先にシリアライズする必要があるため、[`ComputerProvider`][agents.tool.ComputerProvider] ファクトリーを使う prompt 管理フローでは、具体的な `Computer` または `AsyncComputer` インスタンスを渡すか、リクエスト送信前に GA セレクターを強制する必要があります。移行の詳細は [Tools](../tools.md#computertool-and-the-responses-computer-tool) を参照してください。
`context="all_turns"` を使用する場合は、`previous_response_id`、サーバー側の会話、または以前の推論項目の再現によって会話を保持してください。ステートレスな `store=False` 呼び出しでは、レスポンスに `reasoning.encrypted_content` を含め、次のリクエストでそれらの推論項目を再現してください。
#### non-GPT-5 モデル
#### ComputerTool のモデル選択
カスタム `model_settings` なしで non–GPT-5 モデル名を渡すと、SDK は任意モデル互換の汎用 `ModelSettings` に戻ります。
エージェントに [`ComputerTool`][agents.tool.ComputerTool] が含まれている場合、実際の Responses リクエストにおける実効モデルによって、SDK が送信するコンピューターツールのペイロードが決まります。明示的な `gpt-5.5` リクエストでは、GA の組み込み `computer` ツールが使用されます。一方、明示的な `computer-use-preview` リクエストでは、従来の `computer_use_preview` ペイロードが維持されます。
### Responses 専用ツール検索機能
プロンプト管理の呼び出しが主な例外です。プロンプトテンプレートがモデルを所有し、SDK がリクエストから `model` を省略する場合、プロンプトが固定しているモデルを SDK が推測しないように、プレビュー互換のコンピューターペイロードがデフォルトで使用されます。このフローで GA パスを維持するには、リクエストで `model="gpt-5.5"` を明示するか、`ModelSettings(tool_choice="computer")` または `ModelSettings(tool_choice="computer_use")` で GA セレクターを強制します。
次のツール機能は OpenAI Responses モデルでのみサポートされます。
[`ComputerTool`][agents.tool.ComputerTool] が登録されている場合、`tool_choice="computer"``"computer_use"``"computer_use_preview"` は、実効リクエストモデルに一致する組み込みセレクターへ正規化されます。`ComputerTool` が登録されていない場合、これらの文字列は引き続き通常の関数名として動作します。
プレビュー互換のリクエストでは、`environment` と表示サイズを事前にシリアライズする必要があります。そのため、[`ComputerProvider`][agents.tool.ComputerProvider] ファクトリーを使用するプロンプト管理フローでは、具体的な `Computer` または `AsyncComputer` インスタンスを渡すか、リクエスト送信前に GA セレクターを強制する必要があります。移行の詳細については、[ツール](../tools.md#computertool-and-the-responses-computer-tool)を参照してください。
#### GPT-5 以外のモデル
カスタム `model_settings` を指定せずに GPT-5 以外のモデル名を渡すと、SDK はすべてのモデルと互換性のある汎用的な `ModelSettings` に戻ります。
### Responses 専用のツール検索機能
次のツール機能は、OpenAI Responses モデルでのみサポートされます。
- [`ToolSearchTool`][agents.tool.ToolSearchTool]
- [`tool_namespace()`][agents.tool.tool_namespace]
- `@function_tool(defer_loading=True)` と、その他の遅延読み込み Responses ツール
- `@function_tool(defer_loading=True)` およびその他の遅延読み込み対応 Responses ツールサーフェス
これらの機能は Chat Completions モデルおよび non-Responses バックエンドでは拒否されます。遅延読み込みツールを使場合は、エージェントに `ToolSearchTool()` を追加し、素の namespace 名や遅延専用関数名を強制する代わりに、`auto` または `required` tool choice でモデルにツールを読み込ませてください。設定詳細と現時点の制約は [Tools](../tools.md#hosted-tool-search) を参照してください。
これらの機能はChat Completions モデルおよび Responses 以外のバックエンドでは拒否されます。遅延読み込みツールを使用する場合は、エージェントに `ToolSearchTool()` を追加し、修飾されていない名前空間名や遅延読み込み専用関数名を強制する代わりに、`auto` または `required`ツール選択を通じてモデルにツールを読み込ませます。設定詳細と現の制約については、[ツール](../tools.md#hosted-tool-search)を参照してください。
### Responses WebSocket 転送
### Responses WebSocket トランスポート
デフォルトでは、OpenAI Responses API リクエストは HTTP 転送を使います。OpenAI バックエンドのモデル使用時には websocket 転送を有効できます。
デフォルトでは、OpenAI Responses API リクエストは HTTP トランスポートを使用します。OpenAIを基盤とするモデル使用する場合は、WebSocket トランスポートを有効できます。
#### 基本設定
@@ -112,13 +136,13 @@ from agents import set_default_openai_responses_transport
set_default_openai_responses_transport("websocket")
```
これは、デフォルト OpenAI provider で解決される OpenAI Responses モデル `"gpt-5.4"` のような文字列モデル名を含む)に影響します。
これは、デフォルト OpenAIプロバイダーによって解決される OpenAI Responses モデルに影響します。これには `"gpt-5.6-sol"` などの文字列モデル名も含まれます。
転送方式の選択は、SDK がモデル名をモデルインスタンスへ解決するときに行われます。具体的な [`Model`][agents.models.interface.Model] オブジェクトを渡した場合、その転送方式はすでに固定されています。[`OpenAIResponsesWSModel`][agents.models.openai_responses.OpenAIResponsesWSModel] は websocket、[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] は HTTP、[`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] は Chat Completions のままです。`RunConfig(model_provider=...)` を渡す場合、グローバルデフォルトではなくその provider が転送選択を制御します。
トランスポートの選択は、SDK がモデル名をモデルインスタンスへ解決するときに行われます。具体的な [`Model`][agents.models.interface.Model] オブジェクトを渡場合、そのトランスポートはすでに固定されています。[`OpenAIResponsesWSModel`][agents.models.openai_responses.OpenAIResponsesWSModel] は WebSocket、[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] は HTTP を使用し、[`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] は Chat Completions のままです。`RunConfig(model_provider=...)` を渡す場合、グローバルデフォルトではなくそのプロバイダーがトランスポートの選択を制御します。
#### provider / 実行レベル設定
#### プロバイダー単位または実行単位の設定
websocket 転送は provider 単位または実行単位でも設定できます。
プロバイダーごと、または実行ごとに WebSocket トランスポートを設定することもできます。
```python
from agents import Agent, OpenAIProvider, RunConfig, Runner
@@ -127,6 +151,8 @@ provider = OpenAIProvider(
use_responses_websocket=True,
# Optional; if omitted, OPENAI_WEBSOCKET_BASE_URL is used when set.
websocket_base_url="wss://your-proxy.example/v1",
# Optional low-level websocket keepalive settings.
responses_websocket_options={"ping_interval": 20.0, "ping_timeout": 60.0},
)
agent = Agent(name="Assistant")
@@ -137,16 +163,40 @@ result = await Runner.run(
)
```
#### `MultiProvider` による高度なルーティング
OpenAIを基盤とするプロバイダーでは、任意のエージェント登録設定も受け付けます。これは、ハーネス ID など、プロバイダー単位の登録メタデータを OpenAI設定が必要とする場合の高度なオプションです。
接頭辞ベースのモデルルーティングが必要な場合(例: 1 回の実行で `openai/...``litellm/...` のモデル名を混在させる)、[`MultiProvider`][agents.MultiProvider] を使い、そこで `openai_use_responses_websocket=True` を設定してください。
```python
from agents import (
Agent,
OpenAIAgentRegistrationConfig,
OpenAIProvider,
RunConfig,
Runner,
)
`MultiProvider` は 2 つの従来デフォルトを維持しています。
provider = OpenAIProvider(
use_responses_websocket=True,
agent_registration=OpenAIAgentRegistrationConfig(harness_id="your-harness-id"),
)
- `openai/...` は OpenAI provider のエイリアスとして扱われるため、`openai/gpt-4.1` はモデル `gpt-4.1` としてルーティングされます。
- 未知の接頭辞はそのまま渡されず、`UserError` を発生させます。
agent = Agent(name="Assistant")
result = await Runner.run(
agent,
"Hello",
run_config=RunConfig(model_provider=provider),
)
```
OpenAI 互換エンドポイントで、名前空間付きモデル ID の文字列をそのまま期待する場合は、明示的に pass-through 動作を有効化してください。websocket 有効構成では、`MultiProvider` 側でも `openai_use_responses_websocket=True` を維持してください。
#### `MultiProvider` を使用した高度なルーティング
プレフィックスに基づくモデルルーティングが必要な場合、たとえば 1 回の実行で `openai/...``any-llm/...` のモデル名を組み合わせる場合は、[`MultiProvider`][agents.MultiProvider] を使用し、そこで `openai_use_responses_websocket=True` を設定します。
`MultiProvider` は、従来からの 2 つのデフォルト動作を維持します。
- `openai/...` は OpenAIプロバイダーのエイリアスとして扱われるため、`openai/gpt-4.1` はモデル `gpt-4.1` としてルーティングされます。
- 不明なプレフィックスは、そのまま渡されるのではなく `UserError` を発生させます。
OpenAI互換エンドポイントが、名前空間付きのモデル ID を文字どおり受け取ることを想定している場合は、パススルー動作を明示的に有効にしてください。WebSocket を有効にした設定では、`MultiProvider` にも `openai_use_responses_websocket=True` を設定したままにします。
```python
from agents import Agent, MultiProvider, RunConfig, Runner
@@ -172,52 +222,135 @@ result = await Runner.run(
)
```
バックエンドが `openai/...` 文字列リテラルを期待する場合は `openai_prefix_mode="model_id"` を使ます。`openrouter/openai/gpt-4.1-mini` のような他の名前空間付きモデル ID を期待する場合は `unknown_prefix_mode="model_id"` を使ます。これらのオプションは websocket 転送外の `MultiProvider` でも動作します。この例で websocket 有効化しているのは、このセクションで説明している転送設定の一部だからです。同じオプションは [`responses_websocket_session()`][agents.responses_websocket_session] でも利用可能です。
バックエンドが文字どおりの `openai/...` 文字列を想定している場合は`openai_prefix_mode="model_id"` を使用します。バックエンドが `openrouter/openai/gpt-4.1-mini`ど、その他の名前空間付きモデル ID を想定している場合は`unknown_prefix_mode="model_id"` を使用します。これらのオプションは、WebSocket トランスポート以外の `MultiProvider` でも機能します。この例で WebSocket 有効になっているのは、このセクションで説明しているトランスポート設定の一部であるためです。同じオプションは [`responses_websocket_session()`][agents.responses_websocket_session] でも利用できます。
カスタムの OpenAI 互換エンドポイントや proxy を使う場合、websocket 転送には互換 websocket `/responses` エンドポイントも必要です。このような構成では `websocket_base_url` の明示設定が必要になることがあります。
`MultiProvider` を介してルーティングする際に同じプロバイダー単位の登録メタデータが必要な場合は、`openai_agent_registration=OpenAIAgentRegistrationConfig(...)` を渡します。これは基盤となる OpenAIプロバイダーへ転送されます。
#### 注記
カスタムの OpenAI互換エンドポイントまたはプロキシを使用する場合、WebSocket トランスポートには互換性のある WebSocket `/responses` エンドポイントも必要です。そのような設定では、`websocket_base_url` を明示的に設定する必要がある場合があります。
- これは websocket 転送上の Responses API であり、[Realtime API](../realtime/guide.md) ではありません。Chat Completions や、Responses websocket `/responses` エンドポイントをサポートしない non-OpenAI provider には適用されません。
- 環境で未導入の場合は `websockets` パッケージをインストールしてください。
- websocket 転送を有効化後、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を直接使えます。複数ターンのワークフローで同じ websocket 接続をターン間(ネストした agent-as-tool 呼び出しを含む)で再利用したい場合は、[`responses_websocket_session()`][agents.responses_websocket_session] ヘルパーを推奨します。[Running agents](../running_agents.md) ガイドと [`examples/basic/stream_ws.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/stream_ws.py) を参照してください。
#### 注意事項
## non-OpenAI モデル
- これは WebSocket トランスポート経由の Responses API であり、[Realtime API](../realtime/guide.md)ではありません。Chat Completions、および Responses WebSocket `/responses` エンドポイントをサポートしていない OpenAI以外のプロバイダーには適用されません。
- 環境にまだ存在しない場合は、`websockets` パッケージをインストールしてください。
- WebSocket トランスポートを有効にした後、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を直接使用できます。複数ターンのワークフローで、ターン間およびネストされた agent-as-tool 呼び出し間で同じ WebSocket 接続を再利用する場合は、[`responses_websocket_session()`][agents.responses_websocket_session] ヘルパーを推奨します。[エージェントの実行](../running_agents.md)ガイドおよび [`examples/basic/stream_ws.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/stream_ws.py) を参照してください。
- 長時間の推論ターンやレイテンシーが急増するネットワークでは、`responses_websocket_options` を使用して WebSocket のキープアライブ動作をカスタマイズします。遅延した pong フレームを許容するには `ping_timeout` を増やすか、ping を有効にしたままハートビートのタイムアウトを無効にするには `ping_timeout=None` を設定します。WebSocket のレイテンシーより信頼性が重要な場合は、HTTP/SSE トランスポートを優先してください。
- デフォルトでは、SDK は受信メッセージのサイズ制限を無効にします(`max_size=None`)。プロキシの背後で長期間実行されるエージェントプロセスや、メモリ制約のあるコンテナでは、`responses_websocket_options={"max_size": 8 * 1024 * 1024}` を設定して、メッセージごとのメモリ使用量に上限を設けます。
non-OpenAI provider が必要な場合は、まず SDK の組み込み provider 統合ポイントから始めてください。多くの構成では LiteLLM 追加なしで十分です。各パターンの例は [examples/model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) にあります。
### ホスト型マルチエージェント(試験的)
### non-OpenAI provider 統合方法
OpenAI Responses API のホスト型マルチエージェントベータでは、GPT-5.6 のルートモデルがサーバー上でホストされるサブエージェントを作成し、調整できます。Agents SDKは通常の `Runner` を引き続き使用できます。ホスト型オーケストレーションはサービス上で行われ、開発者が定義した関数ツールはアプリケーション内で実行されます。
| アプローチ | 使用する場面 | スコープ |
この統合は試験的であり、ローカル関数の出力を `response.inject` を使用してアクティブなホスト型エージェントへ返せるように、Responses WebSocket トランスポートを使用します。`client.beta.responses.connect` を公開するベータビルドを含む `openai[realtime]>=2.45.0` が必要です。インターフェースとベータ項目のスキーマは、一般提供までに変更される可能性があります。
#### モデルの設定
試験的モジュールからモデルをインポートし、SDK の `Agent` に割り当てます。
```python
from agents import Agent
from agents.extensions.experimental.hosted_multi_agent import OpenAIHostedMultiAgentModel
agent = Agent(
name="Research coordinator",
instructions="Delegate independent research tasks, then synthesize the findings.",
model=OpenAIHostedMultiAgentModel(model="gpt-5.6-sol", config={"max_concurrent_subagents": 3}),
)
```
`OpenAIHostedMultiAgentModel` を構築すると、`multi_agent.enabled` が有効になり、`OpenAI-Beta: responses_multi_agent=v1` WebSocket ヘッダーが送信されます。`openai_client` が指定されていない場合、モデルはデフォルトの OpenAIクライアントを使用します。`max_concurrent_subagents` を省略すると、サービスのデフォルト値が使用されます。
#### ローカル関数ツール
すべてのホスト型エージェントは、リクエストに設定されたモデルとツールを共有します。どのホスト型エージェントが関数を呼び出すかは、Responses API が決定します。通常の SDK Runner は関数をローカルで実行し、同じ呼び出し ID を持つ `function_call_output` をアクティブな WebSocket レスポンスへ注入します。これにより、サービスは元のホスト型呼び出し元を再開できます。関数の実行には、引き続き Runner の通常のガードレール、フック、失敗変換が適用されます。SDK のツール承認による中断はサポートされません。`needs_approval` 設定が `False` ではない関数ツールは、リクエスト送信前に拒否されます。
ツールで呼び出し元を認識したロギングまたは認可が必要な場合は、`get_hosted_agent_metadata()` を使用します。
```python
from typing import Any
from agents import function_tool
from agents.extensions.experimental.hosted_multi_agent import get_hosted_agent_metadata
from agents.tool_context import ToolContext
@function_tool
def lookup_document(ctx: ToolContext[Any], section: str) -> str:
metadata = get_hosted_agent_metadata(ctx)
caller = metadata.agent_name if metadata else "unknown"
print(f"tool caller: {caller}; call ID: {ctx.tool_call_id}")
return f"Contents for {section}"
```
ホスト型エージェントの名前は観測用メタデータであり、ローカルルーティングの仕組みではありません。SDK が提供する呼び出し ID を使用して出力をルーティングしてください。副作用を伴うツールでは、その呼び出し ID を冪等性キーとして使用し、ツールの実行前または実行中に、必要な認可をアプリケーションコードで適用してください。このモデルでは `needs_approval` を使用しないでください。ツールの引数と出力は Responses API の境界を越えます。
#### 出力とストリーミングの動作
フェーズが `final_answer` であり、`/root` に帰属するメッセージのみが通常の最終メッセージになります。試験的アダプターは、サブエージェントのメッセージとホスト型オーケストレーションのレコードを高レベルの `RunResult` から除外します。SDK がそれらのレコードをローカル関数として実行することはありません。
raw ストリーミングでは、ホスト型出力項目や `response.inject.created` 確認応答を含むベータ版 Responses イベントが引き続き公開されます。アダプターは、関数呼び出しの準備が整うと、1 つのアクティブなプロバイダーレスポンスを SDK から見える論理的なモデルターンに分割します。その後、Runner が出力を生成すると、同じプロバイダーレスポンスを再開します。帰属情報を確認するには、raw のホスト型項目または `ToolContext` とともに `get_hosted_agent_metadata()` を使用します。
#### SDK オーケストレーションとの関係
ホスト型マルチエージェントは、SDK のハンドオフおよび agents-as-tools とは別のものです。
- ホスト型マルチエージェントは、OpenAIサービス上でサブエージェントを作成します。アプリケーションがそれらのサブエージェントを作成またはスケジュールすることはありません。
- SDK のハンドオフは、アクティブなローカル SDK `Agent` を変更します。この試験的モデルを使用している場合、すべてのホスト型エージェントが同じハンドオフツールを受け取り、所有権の競合が発生するため、ハンドオフは拒否されます。
- Agents-as-tools は引き続き利用できますが、使用するとクライアント側とサーバー側のオーケストレーションがネストされます。追加のレイテンシー、コスト、ツールの公開範囲を慎重に評価してください。
#### 現在の制限事項
試験的モデルは、`reasoning.summary``max_tool_calls`、および呼び出し元が指定する `multi_agent` または `betas` のオーバーライドを拒否します。Responses の `/compact` エンドポイントはベータ版でサポートされていません。ただし、サービスが各ホスト型エージェントのコンテキストを個別に自動圧縮するため、明示的な `context_management.compact_threshold` は使用できます。
1 つの `OpenAIHostedMultiAgentModel` インスタンスが同時に保持できるアクティブなホスト型レスポンスは、最大 1 つです。ローカル関数の出力を待機している間に実行が放棄された場合は、`await model.close()` を呼び出して WebSocket を解放してください。実行中のホスト型レスポンスを別のプロセスまたはイベントループで復元することは、現在サポートされていません。
基盤となる Responses API ベータの動作については、[OpenAI マルチエージェントガイド](https://developers.openai.com/api/docs/guides/tools-multi-agent)を参照してください。非ストリーミングおよびストリーミングでの SDK の使用方法については、[`examples/agent_patterns/hosted_multi_agent_beta.py`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns/hosted_multi_agent_beta.py) を参照してください。
## OpenAI以外のモデル
OpenAI以外のプロバイダーが必要な場合は、SDK の組み込みプロバイダー統合ポイントから始めてください。多くの設定では、サードパーティ製アダプターを追加しなくても、これで十分です。各パターンのコード例は、[examples/model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) にあります。
### OpenAI以外のプロバイダーの統合方法
| アプローチ | 使用する場合 | 適用範囲 |
| --- | --- | --- |
| [`set_default_openai_client`][agents.set_default_openai_client] | 1 つの OpenAI 互換エンドポイントを、ほとんどまたはすべてのエージェントのデフォルトにしたい | グローバルデフォルト |
| [`ModelProvider`][agents.models.interface.ModelProvider] | 1 つのカスタム provider を単一実行に適用したい | 実行単位 |
| [`Agent.model`][agents.agent.Agent.model] | エージェントごとに異なる provider または具体的モデルオブジェクトが必要 | エージェント単位 |
| LiteLLM (beta) | LiteLLM 固有の provider カバレッジルーティングが必要 | [LiteLLM](#litellm) を参照 |
| [`set_default_openai_client`][agents.set_default_openai_client] | 1 つの OpenAI互換エンドポイントを、ほとんどまたはすべてのエージェントのデフォルトにする場合 | グローバルデフォルト |
| [`ModelProvider`][agents.models.interface.ModelProvider] | 1 つのカスタムプロバイダーを単一実行に適用する場合 | 実行単位 |
| [`Agent.model`][agents.agent.Agent.model] | エージェントごとに異なるプロバイダーまたは具体的モデルオブジェクトが必要な場合 | エージェント単位 |
| サードパーティ製アダプター | 組み込みの方法では提供されない、アダプター管理のプロバイダーカバレッジまたはルーティングが必要な場合 | [サードパーティ製アダプター](#third-party-adapters)を参照 |
これらの組み込み経路で他の LLM provider を統合できます。
の組み込み方法を使用して、他の LLM プロバイダーを統合できます。
1. [`set_default_openai_client`][agents.set_default_openai_client] は、`AsyncOpenAI` インスタンスを LLM クライアントとしてグローバルに使いたい場合に有用です。LLM provider が OpenAI 互換 API エンドポイントを持ち、`base_url``api_key` を設定できる場合に使ます。設定可能な例は [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) を参照してください。
2. [`ModelProvider`][agents.models.interface.ModelProvider] は `Runner.run` レベルです。これにより「この実行のエージェントでカスタム model provider を使う」と指定できます。設定可能な例は [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) を参照してください。
3. [`Agent.model`][agents.agent.Agent.model] では特定 Agent インスタンスモデルを指定できます。これによりエージェントごとに異なる provider を組み合わせられます。設定可能な例は [examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py) を参照してください。
1. [`set_default_openai_client`][agents.set_default_openai_client] は、`AsyncOpenAI` インスタンスを LLM クライアントとしてグローバルに使用する場合に役立ちます。これは、LLM プロバイダーが OpenAI互換 API エンドポイントを持ち、`base_url``api_key` を設定できる場合に使用します。設定可能なコード例については、[examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) を参照してください。
2. [`ModelProvider`][agents.models.interface.ModelProvider] は `Runner.run` レベルで使用します。これにより「この実行内のすべてのエージェントでカスタムモデルプロバイダーを使用する」と指定できます。設定可能なコード例については、[examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) を参照してください。
3. [`Agent.model`][agents.agent.Agent.model] を使用すると、特定 Agent インスタンスモデルを指定できます。これによりエージェントごとに異なるプロバイダーを組み合わせて使用できます。設定可能なコード例については、[examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py) を参照してください。
`platform.openai.com` の API key がない場合は、`set_tracing_disabled()` トレーシングを無効するか、[別のトレーシングプロセッサー](../tracing.md) を設定することを推奨します。
`platform.openai.com` の API キーを持っていない場合は、`set_tracing_disabled()` を使用してトレーシングを無効するか、[別のトレーシングプロセッサー](../tracing.md)を設定することを推奨します。
``` python
from agents import Agent, AsyncOpenAI, OpenAIChatCompletionsModel, set_tracing_disabled
set_tracing_disabled(disabled=True)
client = AsyncOpenAI(api_key="Api_Key", base_url="Base URL of Provider")
model = OpenAIChatCompletionsModel(model="Model_Name", openai_client=client)
agent= Agent(name="Helping Agent", instructions="You are a Helping Agent", model=model)
```
!!! note
これらの例では、Chat Completions API / model を使っています。多くの LLM provider がまだ Responses API をサポートしていないためです。LLM provider が対応している場合は Responses の用を推奨します。
これらのコード例では、多くの LLM プロバイダーがまだ Responses API をサポートしていないため、Chat Completions API/モデルを使用しています。LLM プロバイダーが Responses API をサポートしている場合はResponses の使用を推奨します。
## 1 つのワークフローでのモデル混在
## 単一ワークフローでのモデルの組み合わせ
単一ワークフロー内で、エージェントごとに異なるモデルを使たい場合があります。たとえば、トリアージには小さく高速なモデルを使、複雑なタスクには大きく高性能なモデルを使う、といった構成です。[`Agent`][agents.Agent] を設定する、次のいずれかで特定モデルを選択できます。
単一ワークフロー内で、エージェントごとに異なるモデルを使用したい場合があります。たとえば、トリアージには小型で高速なモデルを使用し、複雑なタスクには大型で高性能なモデルを使用できます。[`Agent`][agents.Agent] を設定する場合、次のいずれかの方法で特定モデルを選択できます。
1. モデル名を渡す。
2. 任意のモデル名 + その名前を Model インスタンスにマッできる [`ModelProvider`][agents.models.interface.ModelProvider] を渡す。
3. [`Model`][agents.models.interface.Model] 実装を直接す。
1. モデル名を渡します。
2. 任意のモデル名と、その名前を Model インスタンスにマッピングできる [`ModelProvider`][agents.models.interface.ModelProvider] を渡します。
3. [`Model`][agents.models.interface.Model] 実装を直接指定します。
!!! note
SDK は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] と [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] の両方をサポートしていますが、2 つは対応機能ツール集合が異なるため、ワークフローごとに単一のモデル形を使ことを推奨します。モデル形状を混在させる必要がある場合は、用する機能が両方で使えることを確認してください。
SDK は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] と [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] の両方の形式をサポートしていますが、2 つの形式でサポートされる機能ツールのセットが異なるため、ワークフローごとに 1 つのモデル形を使用することを推奨します。ワークフローで複数のモデル形式を組み合わせる必要がある場合は、使用するすべての機能が両方で利用できることを確認してください。
```python
from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel
@@ -242,7 +375,7 @@ triage_agent = Agent(
name="Triage agent",
instructions="Handoff to the appropriate agent based on the language of the request.",
handoffs=[spanish_agent, english_agent],
model="gpt-5.4",
model="gpt-5.6-sol",
)
async def main():
@@ -250,10 +383,10 @@ async def main():
print(result.final_output)
```
1. OpenAI モデルを直接設定します。
2. [`Model`][agents.models.interface.Model] 実装を提供します。
1. OpenAIモデルの名前を直接設定します。
2. [`Model`][agents.models.interface.Model] 実装を指定します。
エージェントで使モデルをさらに設定したい場合は、temperature などの任意モデル設定パラメーターを提供する [`ModelSettings`][agents.models.interface.ModelSettings] を渡せます。
エージェントで使用するモデルをさらに設定する場合は、temperature などの任意モデル設定パラメーターを提供する [`ModelSettings`][agents.models.interface.ModelSettings] を渡せます。
```python
from agents import Agent, ModelSettings
@@ -266,46 +399,82 @@ english_agent = Agent(
)
```
## 高度な OpenAI Responses 設定
## OpenAI Responses の高度な設定
OpenAI Responses 経路でより細かな制御が必要な場合は、`ModelSettings` から始めてください。
OpenAI Responses パスを使用していて、より詳細な制御が必要な場合は、`ModelSettings` から始めてください。
### 一般的な高度 `ModelSettings` オプション
### 一般的な高度 `ModelSettings` オプション
OpenAI Responses API 利用時は、いくつかのリクエストフィールドに直接対応する `ModelSettings` フィールドがすでにあるため、それらに `extra_args` は不要です
OpenAI Responses API を使用する場合、いくつかのリクエストフィールドにはすでに対応する `ModelSettings` フィールドが用意されているため、それらに `extra_args` を使用する必要はありません
- `parallel_tool_calls`: 同ターンで複数 tool call を許可 / 禁止します。
- `truncation`: `"auto"` を設定すると、コンテキスト超過時に失敗せず、Responses API が最も古い会話項目を削除します。
- `store`: 生成レスポンスを後続取得のためサーバー側保存するかを制御します。レスポンス ID に依存するフォローアップワークフローや、`store=False`にローカル入力へフォールバックが必要セッション圧縮フローで重要です。
- `prompt_cache_retention`: たとえば `"24h"` のように、キャッシュされた prompt 接頭辞をより長く保持します。
- `response_include`: `web_search_call.action.sources``file_search_call.results``reasoning.encrypted_content` など、より豊富なレスポンスペイロードを要求します。
- `top_logprobs`: 出力テキストの上位 token logprobs を要求します。SDK は `message.output_text.logprobs` も自動追加します。
- `retry`: モデル呼び出しに対する runner 管理 retry 設定を有効化します。[Runner 管理リトライ](#runner-managed-retries) を参照してください。
- `parallel_tool_calls`: 同ターンで複数のツール呼び出しを許可または禁止します。
- `truncation`: コンテキストが上限を超える場合に失敗する代わりに、Responses API が最も古い会話項目を削除できるようにするには、`"auto"` を設定します。
- `store`: 生成されたレスポンスを、後で取得できるようにサーバー側保存するかどうかを制御します。これは、レスポンス ID に依存する後続ワークフローや、`store=False` の場合にローカル入力へフォールバックが必要になる可能性があるセッション圧縮フローに関係します。
- `context_management`: `compact_threshold` を使用した Responses 圧縮など、サーバー側のコンテキスト処理を設定します。
- `prompt_cache_retention`: 以前のモデルファミリー向けに、たとえば
`"24h"` を使用して保持期間の延長を設定します。
- `prompt_cache_options`: 暗黙的または明示的なプロンプトキャッシュを選択し、GPT-5.6 では `"30m"` のキャッシュ TTL を設定します。
- `response_include`: `web_search_call.action.sources`、`file_search_call.results`、`reasoning.encrypted_content` など、より詳細なレスポンスペイロードをリクエストします。
- `top_logprobs`: 出力テキストについて、上位トークンの logprobs をリクエストします。SDK は `message.output_text.logprobs` も自動的に追加します。
- `retry`: モデル呼び出しに対して Runner 管理の再試行設定を有効にします。[Runner 管理の再試行](#runner-managed-retries)を参照してください。
```python
from agents import Agent, ModelSettings
research_agent = Agent(
name="Research agent",
model="gpt-5.4",
model="gpt-5.6-sol",
model_settings=ModelSettings(
parallel_tool_calls=False,
truncation="auto",
store=True,
prompt_cache_retention="24h",
context_management=[{"type": "compaction", "compact_threshold": 200000}],
prompt_cache_options={"mode": "explicit", "ttl": "30m"},
response_include=["web_search_call.action.sources"],
top_logprobs=5,
),
)
```
`store=False` を設定すると、Responses API はそのレスポンスを後続のサーバー側取得に利用できる状態で保持しません。これは stateless または zero-data-retention 風フローで有用ですが、通常レスポンス ID を再利用する機能は、代わりにローカル管理状態へ依存する必要があります。たとえば [`OpenAIResponsesCompactionSession`][agents.memory.openai_responses_compaction_session.OpenAIResponsesCompactionSession] は、最後のレスポンスが保存されていない場合、デフォルト `"auto"` 圧縮経路を入力ベース圧縮へ切り替えます。[Sessions ガイド](../sessions/index.md#openai-responses-compaction-sessions) を参照してください
明示的なプロンプトキャッシュでは、再利用可能なプレフィックスの末尾にあるコンテンツ部分へブレークポイントを追加します。同じ `ModelSettings.prompt_cache_options` フィールドが Responses と Chat Completions のリクエストに渡され、Chat Completions コンバーターは、テキスト、画像、音声、ファイルのコンテンツ部分にあるブレークポイントを保持します
```python
from agents import Runner
result = await Runner.run(
research_agent,
[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Reusable background material...",
"prompt_cache_breakpoint": {"mode": "explicit"},
},
{
"type": "input_text",
"text": "Analyze the latest question.",
},
],
}
],
)
```
`prompt_cache_retention` は、従来の保持制御を使用する以前のモデルファミリーでも引き続き
利用できます。直接指定する `ModelSettings` フィールドと同じキーを
`extra_args` に含めないでください。
`store=False` を設定すると、Responses API はそのレスポンスを後でサーバー側から取得できる状態で保持しません。これはステートレスまたはゼロデータ保持形式のフローに役立ちますが、通常であればレスポンス ID を再利用する機能が、代わりにローカルで管理された状態へ依存する必要があることも意味します。たとえば、最後のレスポンスが保存されていない場合、[`OpenAIResponsesCompactionSession`][agents.memory.openai_responses_compaction_session.OpenAIResponsesCompactionSession] は、デフォルトの `"auto"` 圧縮パスを入力ベースの圧縮へ切り替えます。[セッションガイド](../sessions/index.md#openai-responses-compaction-sessions)を参照してください。
サーバー側の圧縮は、[`OpenAIResponsesCompactionSession`][agents.memory.openai_responses_compaction_session.OpenAIResponsesCompactionSession] とは異なります。`context_management=[{"type": "compaction", "compact_threshold": ...}]` は Responses API リクエストごとに送信され、レンダリングされたコンテキストがしきい値を超えると、API はレスポンスの一部として圧縮項目を出力できます。`OpenAIResponsesCompactionSession` は、ターン間で独立した `responses.compact` エンドポイントを呼び出し、ローカルのセッション履歴を書き換えます。
### `extra_args` の受け渡し
SDK がまだトップレベルで直接公開していない provider 固有または新しいリクエストフィールドが必要な場合は `extra_args` を使ます。
SDK がまだトップレベルで直接公開していない、プロバイダー固有または新しいリクエストフィールドが必要な場合は、`extra_args` を使用します。
また OpenAI の Responses API を使場合、[他にもいくつかの任意パラメーター](https://platform.openai.com/docs/api-reference/responses/create)例: `user``service_tier` など)があります。トップレベルない場合は、`extra_args` で渡せます。
またOpenAIの Responses API を使用する場合、[他にもいくつかの任意パラメーターがあります](https://platform.openai.com/docs/api-reference/responses/create)たとえば `user`、`service_tier` など)。トップレベルで利用できない場合は、`extra_args` を使用して渡すこともできます。同じリクエストフィールドを、直接指定する `ModelSettings` フィールドでも設定しないでください。
```python
from agents import Agent, ModelSettings
@@ -321,16 +490,16 @@ english_agent = Agent(
)
```
## Runner 管理リトライ
## Runner 管理の再試行
リトライは実行時限定で、明示的な opt-in です。`ModelSettings(retry=...)` を設定し、かつ retry policy が再試行を選択しない限り、SDK は一般的なモデルリクエストをリトライしません。
再試行は実行時のみ有効で、オプトイン方式です。`ModelSettings(retry=...)` を設定し、再試行ポリシーが再試行を選択しない限り、SDK は一般的なモデルリクエストを再試行しません。
```python
from agents import Agent, ModelRetrySettings, ModelSettings, retry_policies
agent = Agent(
name="Assistant",
model="gpt-5.4",
model="gpt-5.6-sol",
model_settings=ModelSettings(
retry=ModelRetrySettings(
max_retries=4,
@@ -357,79 +526,114 @@ agent = Agent(
| フィールド | 型 | 注記 |
| --- | --- | --- |
| `max_retries` | `int | None` | 初回リクエスト後に許可される再試行回数です。 |
| `backoff` | `ModelRetryBackoffSettings | dict | None` | policy が明示的 delay を返さずに再試行するときのデフォルト遅延戦略です。 |
| `policy` | `RetryPolicy | None` | 再試行するかを決るコールバックです。このフィールドは実行時限定でシリアライズされません。 |
| `max_retries` | `int | None` | 最初のリクエスト後に許可される再試行回数です。 |
| `backoff` | `ModelRetryBackoffSettings | dict | None` | ポリシーが明示的な遅延を返さずに再試行する場合の、デフォルト遅延戦略です。`backoff.max_delay` は、計算されたこのバックオフ遅延のみに上限を設定します。ポリシーが返す明示的な遅延や retry-after ヒントには上限を設定しません。 |
| `policy` | `RetryPolicy | None` | 再試行するかどうかを決定するコールバックです。このフィールドは実行時のみ有効で、シリアライズされません。 |
</div>
retry policy は [`RetryPolicyContext`][agents.retry.RetryPolicyContext] を受け取ります。内容は以下です。
再試行ポリシーは、次の情報を持つ [`RetryPolicyContext`][agents.retry.RetryPolicyContext] を受け取ります。
- `attempt``max_retries`(試行回数に応じた判断に使用
- `stream`streamed / non-streamed で分岐可能)
- `error`raw 検査用)
- `status_code``retry_after``error_code``is_network_error``is_timeout``is_abort` などの `normalized` 情報
- 下位モデルアダプターが retry ガイダンスを提供できる場合`provider_advice`
- `attempt` と `max_retries`: 試行回数を考慮した判断に使用できます
- `stream`: ストリーミング動作と非ストリーミング動作を分岐できます
- `error`: raw の内容を調べるために使用します
- `normalized`: `status_code`、`retry_after`、`error_code`、`is_network_error`、`is_timeout`、`is_abort` などの正規化された情報です
- `provider_advice`: 基盤となるモデルアダプターが再試行に関するガイダンスを提供できる場合に設定されます
policy は次のいずれかを返せます。
ポリシーは、次のいずれかを返せます。
- 単純な再試行判定としての `True` / `False`
- delay 上書きや診断理由付与を行いたい場合の [`RetryDecision`][agents.retry.RetryDecision]。
- 単純な再試行判断を行う場合は、`True` / `False`。
- 遅延を上書きするか、診断用の理由を付加する場合は、[`RetryDecision`][agents.retry.RetryDecision]。
SDK は `retry_policies` に既製ヘルパーを提供しています。
SDK は、`retry_policies` でそのまま利用できるヘルパーを公開しています。
| ヘルパー | 振る舞い |
| ヘルパー | 動作 |
| --- | --- |
| `retry_policies.never()` | 常に opt-out します。 |
| `retry_policies.provider_suggested()` | 利用可能な場合、provider の retry 推奨に従います。 |
| `retry_policies.network_error()` | 一時的な転送 / timeout 障害に一致します。 |
| `retry_policies.http_status([...])` | 選択た HTTP status code に一致します。 |
| `retry_policies.retry_after()` | retry-after ヒントがある場合のみ、その delay で再試行します。 |
| `retry_policies.any(...)` | ネスト policy のいずれかが opt-in したとき再試行します。 |
| `retry_policies.all(...)` | ネスト policy のすべてが opt-in したときのみ再試行します。 |
| `retry_policies.never()` | 常に再試行を行いません。 |
| `retry_policies.provider_suggested()` | 利用可能な場合、プロバイダーの再試行アドバイスに従います。 |
| `retry_policies.network_error()` | 一時的なトランスポート障害およびタイムアウト障害に一致します。 |
| `retry_policies.http_status([...])` | 選択された HTTP ステータスコードに一致します。 |
| `retry_policies.retry_after()` | retry-after ヒントが利用可能な場合のみ、その遅延を使用して再試行します。このヘルパーは retry-after 値を明示的なポリシー遅延として扱うため、`backoff.max_delay` による上限は適用されません。 |
| `retry_policies.any(...)` | ネストされたポリシーのいずれかが再試行を選択した場合に再試行します。 |
| `retry_policies.all(...)` | ネストされたすべてのポリシーが再試行を選択した場合にのみ再試行します。 |
policy を組み合わせる場合、`provider_suggested()`最も安全な最初の構成要素です。provider が判別可能な場合、provider veto と replay-safety 承認を保持できるためです。
ポリシーを組み合わせる場合、プロバイダーが再実行の安全性を区別できるときに、プロバイダーによる拒否と再実行の安全性に関する承認を維持できるため、`provider_suggested()` が最も安全な最初の基本要素です。
##### 安全境界
##### 安全性の境界
次の障害は自動再試行されません。
一部の失敗は自動的に再試行されません。
- Abort エラー。
- provider アドバイスが replay unsafe と判定したリクエスト。
- 出力がすでに始まっており replay が unsafe になる streamed 実行。
- 中止エラー。
- プロバイダーのアドバイスにより、再実行が安全ではないと示されたリクエスト。
- 出力がすでに開始され、再実行が安全でなくなる状態になったストリーミング実行。
`previous_response_id` または `conversation_id` を使う状態付きフォローアップリクエストも、より保守的に扱われます。これらのリクエストでは `network_error()``http_status([500])` のような非 provider 判定だけでは不十分です。retry policy には通常 `retry_policies.provider_suggested()` を通じた provider の replay-safe 承認を含める必要があります。
`previous_response_id` または `conversation_id` を使用するステートフルな後続リクエストも、より保守的に扱われます。これらのリクエストでは、`network_error()` や `http_status([500])` など、プロバイダー由来ではない条件だけでは不十分です。再試行ポリシーには通常 `retry_policies.provider_suggested()` を通じて、プロバイダーから再実行が安全であることの承認を含める必要があります。
##### Runner とエージェントのマージ挙動
##### Runner とエージェントのマージ動作
`retry` は runner レベルとエージェントレベルの `ModelSettings` 間で deep-merge されます。
`retry` は、Runner レベルとエージェントレベルの `ModelSettings` の間でディープマージされます。
- エージェントは `retry.max_retries` のみを上書きしつつ、runner の `policy` を継承できます。
- エージェントは `retry.backoff` の一部のみを上書きし、他の backoff フィールドは runner から維持できます。
- `policy` は実行時限定のため、シリアライズされた `ModelSettings``max_retries``backoff` を保持し、コールバック自体は省略します
- エージェントは `retry.max_retries` のみを上書きし、Runner の `policy` を継承できます。
- エージェントは `retry.backoff` の一部のみを上書きし、Runner の他のバックオフフィールドを維持できます。
- `policy` は実行時のみ有効であるため、シリアライズされた `ModelSettings` には `max_retries` と `backoff` が保持されますが、コールバック自体は含まれません
より完全な例は [`examples/basic/retry.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/retry.py) と [`examples/basic/retry_litellm.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/retry_litellm.py) を参照してください。
より詳しいコード例については、[`examples/basic/retry.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/retry.py) および[アダプターを使用した再試行のコード例](https://github.com/openai/openai-agents-python/tree/main/examples/basic/retry_litellm.py)を参照してください。
## non-OpenAI provider のトラブルシューティング
## OpenAI以外のプロバイダーのトラブルシューティング
### トレーシングクライアントエラー 401
### トレーシングクライアント 401 エラー
トレーシング関連エラーがる場合、トレースが OpenAI サーバーへアップロードされる一方で OpenAI API key がないことが原因です。解決方法は 3 つあります。
トレーシング関連するエラーが発生する場合、トレースが OpenAIサーバーへアップロードされる一方でOpenAI API キーがないことが原因です。解決方法は 3 つあります。
1. トレーシングを完全に無効化する: [`set_tracing_disabled(True)`][agents.set_tracing_disabled]。
2. トレーシング用 OpenAI key を設定する: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。この API key はトレースアップロード専用で、[platform.openai.com](https://platform.openai.com/) 由来である必要があります。
3. non-OpenAI トレースプロセッサーを使う。[tracing docs](../tracing.md#custom-tracing-processors) を参照してください。
1. トレーシングを完全に無効にします: [`set_tracing_disabled(True)`][agents.set_tracing_disabled]。
2. トレーシング用 OpenAIキーを設定します: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。この API キーはトレースアップロードにのみ使用され、[platform.openai.com](https://platform.openai.com/) から取得したものである必要があります。
3. OpenAI以外のトレースプロセッサーを使用します。[トレーシングのドキュメント](../tracing.md#custom-tracing-processors)を参照してください。
### Responses API サポート
### Responses API サポート
SDK はデフォルトで Responses API を使ますが、多くの LLM provider はまだ対応していません。その結果 404 などの問題が発生することがあります。解決方法は 2 つあります。
SDK はデフォルトで Responses API を使用しますが、他の多くの LLM プロバイダーはまだサポートしていません。その結果404 または同様の問題が発生する場合があります。解決方法は 2 つあります。
1. [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api] を呼び出します。これは環境変数`OPENAI_API_KEY``OPENAI_BASE_URL` を設定している場合に機能します。
2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] を使ます。例は [こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) にあります。
1. [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api] を呼び出します。これは環境変数を通じて `OPENAI_API_KEY` と `OPENAI_BASE_URL` を設定している場合に機能します。
2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] を使用します。コード例は[こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)にあります。
### structured outputs サポート
### Chat Completions の互換性オプション
一部の model provider は [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) をサポートしていません。これにより、次のようなエラーが出る場合があります。
Chat Completions を介してルーティングする場合、SDK は、`previous_response_id`、`conversation_id`、プロンプト、テキスト以外を含むツール出力など、Chat Completions では送信できない Responses 専用フィールドを暗黙的に削除することで互換性を維持します。開発中にこれらの不一致を早期にエラーにしたい場合は、OpenAIプロバイダーで厳密な機能検証を有効にします。
```python
from agents import Agent, OpenAIProvider, RunConfig, Runner
provider = OpenAIProvider(
use_responses=False,
strict_feature_validation=True,
)
agent = Agent(name="Assistant")
result = await Runner.run(
agent,
"Hello",
run_config=RunConfig(model_provider=provider),
)
```
[`MultiProvider`][agents.MultiProvider] を使用する場合は、代わりに `openai_strict_feature_validation=True` を渡します。
一部の OpenAI互換 Chat Completions プロバイダーは、SDK が増分処理するには十分な信頼性がないチャンク形式で、ツール呼び出しの差分をストリーミングします。その場合は、ストリーミングされたツール呼び出しのバッファリングを有効にし、プロバイダーのストリームが終了した後にのみ SDK がツール呼び出しを出力するようにします。
```python
from agents import OpenAIProvider
provider = OpenAIProvider(
use_responses=False,
buffer_streamed_tool_calls=True,
)
```
[`MultiProvider`][agents.MultiProvider] では、`openai_buffer_streamed_tool_calls=True` を使用します。
### structured outputs のサポート
一部のモデルプロバイダーは、[structured outputs](https://platform.openai.com/docs/guides/structured-outputs)をサポートしていません。その結果、次のようなエラーが発生することがあります。
```
@@ -437,24 +641,34 @@ BadRequestError: Error code: 400 - {'error': {'message': "'response_format.type'
```
これは一部 model provider 側の制約です。JSON 出力はサポートしていても、出力に使う `json_schema` の指定を許可しません。この問題の修正に取り組んでいますが、JSON schema 出力をサポートする provider の利用を推奨します。そうない場合、アプリは不正な JSON によって頻繁に壊れる可能性があります。
これは一部のモデルプロバイダーの制約です。JSON 出力には対応していますが、出力に使用する `json_schema` を指定できません。この問題の修正に取り組んでいますが、JSON スキーマ出力をサポートするプロバイダーを利用することを推奨します。そうないと、不正な形式の JSON によってアプリが頻繁に動作しなくなる可能性があります。
## provider 間でのモデル混在
## プロバイダー間でのモデルの組み合わせ
model provider 間の機能差を把握していないとエラーになる可能性があります。たとえば OpenAI は structured outputs、マルチモーダル入力、ホスト型ファイル検索と Web 検索をサポートしますが、多くの他 provider はこれらをサポートしません。次の制に注意してください。
モデルプロバイダー間の機能差を把握しておく必要があります。そうしないとエラーが発生する可能性があります。たとえばOpenAIは structured outputs、マルチモーダル入力、ホスト型ファイル検索と Web 検索をサポートしていますが、他の多くのプロバイダーはこれらの機能をサポートしていません。次の制に注意してください。
- 未対応 provider に、未対応の `tools` を送らない
- テキスト専用モデル呼び出前に、マルチモーダル入力を除外する
- structured JSON 出力非対応 provider は、ときどき不正な JSON 生成する点に注意する
- サポートされていない `tools` を、それらを解釈できないプロバイダーへ送信しないでください
- テキスト専用モデル呼び出前に、マルチモーダル入力を除外してください
- 構造化された JSON 出力をサポートしていないプロバイダーでは、無効な JSON 生成される場合があることに注意してください。
## LiteLLM
## サードパーティ製アダプター
LiteLLM サポートは、non-OpenAI provider を Agents SDK ワークフローへ取り込む必要があるケース向けに、best-effort の beta として提供されています。
SDK の組み込みプロバイダー統合ポイントでは不十分な場合にのみ、サードパーティ製アダプターを使用してください。この SDK で OpenAIモデルのみを使用する場合は、Any-LLM や LiteLLM ではなく、組み込みの [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] パスを優先してください。サードパーティ製アダプターは、OpenAIモデルと OpenAI以外のプロバイダーを組み合わせる必要がある場合、または組み込みの方法では提供されない、アダプター管理のプロバイダーカバレッジやルーティングが必要な場合に使用します。アダプターは SDK と上流のモデルプロバイダーの間に互換性レイヤーを追加するため、機能のサポートとリクエストのセマンティクスはプロバイダーによって異なる場合があります。SDK には現在、ベストエフォート方式のベータ版アダプター統合として Any-LLM と LiteLLM が含まれています。
この SDK で OpenAI モデルを使う場合は、LiteLLM ではなく組み込みの [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 経路を推奨します。
### Any-LLM
OpenAI モデルと non-OpenAI provider を組み合わせる必要があり、とくに Chat Completions 互換 API 経由で使う場合、LiteLLM は beta オプションとして利用できますが、すべての構成で最適とは限りません
Any-LLM のサポートは、Any-LLM が管理するプロバイダーカバレッジまたはルーティングが必要な場合に向けて、ベストエフォート方式のベータ版として含まれています
non-OpenAI provider で LiteLLM が必要な場合は `openai-agents[litellm]` をインストールし、[`examples/model_providers/litellm_auto.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/litellm_auto.py) または [`examples/model_providers/litellm_provider.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/litellm_provider.py) から始めてください。`litellm/...` モデル名を使うか、[`LitellmModel`][agents.extensions.models.litellm_model.LitellmModel] を直接インスタンス化できます。
上流のプロバイダーパスに応じて、Any-LLM は Responses API、Chat Completions 互換 API、またはプロバイダー固有の互換性レイヤーを使用する場合があります。
LiteLLM のレスポンスで SDK の usage metrics を埋めたい場合は、`ModelSettings(include_usage=True)` を渡してください。
Any-LLM が必要な場合は、`openai-agents[any-llm]` をインストールし、[`examples/model_providers/any_llm_auto.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/any_llm_auto.py) または [`examples/model_providers/any_llm_provider.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/any_llm_provider.py) から始めてください。[`MultiProvider`][agents.MultiProvider] で `any-llm/...` モデル名を使用するか、`AnyLLMModel` を直接インスタンス化するか、実行スコープで `AnyLLMProvider` を使用できます。モデルサーフェスを明示的に固定する必要がある場合は、`AnyLLMModel` の構築時に `api="responses"` または `api="chat_completions"` を渡します。
Any-LLM は引き続きサードパーティ製アダプターレイヤーであるため、プロバイダーの依存関係と機能差は SDK ではなく、上流の Any-LLM によって定義されます。上流のプロバイダーが使用量指標を返す場合、それらは自動的に伝播されます。ただし、ストリーミング対応の Chat Completions バックエンドでは、使用量チャンクを出力する前に `ModelSettings(include_usage=True)` が必要になる場合があります。structured outputs、ツール呼び出し、使用量レポート、または Responses 固有の動作に依存する場合は、デプロイ予定の正確なプロバイダーバックエンドを検証してください。
### LiteLLM
LiteLLM のサポートは、LiteLLM 固有のプロバイダーカバレッジまたはルーティングが必要な場合に向けて、ベストエフォート方式のベータ版として含まれています。
LiteLLM が必要な場合は、`openai-agents[litellm]` をインストールし、[`examples/model_providers/litellm_auto.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/litellm_auto.py) または [`examples/model_providers/litellm_provider.py`](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/litellm_provider.py) から始めてください。`litellm/...` モデル名を使用するか、[`LitellmModel`][agents.extensions.models.litellm_model.LitellmModel] を直接インスタンス化できます。
LiteLLM を基盤とする一部のプロバイダーは、デフォルトでは SDK の使用量指標を設定しません。使用量レポートが必要な場合は、`ModelSettings(include_usage=True)` を渡してください。また、structured outputs、ツール呼び出し、使用量レポート、またはアダプター固有のルーティング動作に依存する場合は、デプロイ予定の正確なプロバイダーバックエンドを検証してください。
+2 -2
View File
@@ -5,9 +5,9 @@ search:
# LiteLLM
<script>
window.location.replace("../#litellm");
window.location.replace("../#third-party-adapters");
</script>
このページは [Models の LiteLLM セクション](index.md#litellm)に移動しました。
このページは [Models のサードパーティアダプターセクション](index.md#third-party-adapters) に移動しました。
自動的にリダイレクトされない場合は、上記のリンクを使用してください。
+33 -33
View File
@@ -4,61 +4,61 @@ search:
---
# エージェントオーケストレーション
オーケストレーションとは、アプリ内でのエージェントの流れを指します。どのエージェント、どの順序で実行され、次に何が起こるかをどのように決定するか、ということです。エージェントをオーケストレーションする主な方法は 2 つあります
オーケストレーションとは、アプリ内でのエージェントの流れを指します。どのエージェント、どの順序で実行、次に何が起こるかをどのように決定するか、ということです。エージェントをオーケストレーションする主な方法は 2 つあります
1. LLM に意思決定させる: LLM の知を使って計画推論を行い、それに基づいてどのステップを取るかを決定します。
2. コードオーケストレーションする: コードによってエージェントの流れを決定します。
1. LLM に判断を任せる:LLM の知を使って計画推論を行い、それに基づいて取る手順を決定します。
2. コードによるオーケストレーション:コードでエージェントの流れを決定します。
これらのパターンは組み合わせて使えます。それぞれにトレードオフがあり、以下で説明します。
これらのパターンは組み合わせることができます。それぞれにトレードオフがあり、以下で説明します。
## LLM によるオーケストレーション
エージェントは、instructions、tools、ハンドオフを備えた LLM です。つまり、オープンエンドなタスクが与えられた場合、LLM はそのタスクへの取り組み方を自律的に計画でき、tools を使ってアクションを実行しデータを取得し、ハンドオフを使ってサブエージェントにタスクを委できます。たとえば、リサーチエージェントには次のようなツールを備えられます
エージェントは、instructions、tools、ハンドオフを備えた LLM です。つまり、自由度の高いタスクが与えられた場合、LLM は、tools を使ってアクションを実行しデータを取得し、ハンドオフを使ってサブエージェントにタスクを委任しながら、そのタスクへの取り組み方を自律的に計画できます。たとえば、リサーチエージェントには次のようなツールを備えられます
- オンライン情報を見つけるための Web 検索
- オンライン情報を見つけるための Web 検索
- 独自データや接続先を検索するためのファイル検索と取得
- コンピュータ上でアクションを実行するためのコンピュータ操作
- コンピュータ上でアクションを実行するためのコンピュータ操作
- データ分析を行うためのコード実行
- 計画、レポート作成などに優れた専門エージェントへのハンドオフ
- 計画、レポート作成などに優れた専門エージェントへのハンドオフ
### SDK の中核パターン
### コア SDK パターン
Python SDK では、次の 2 つのオーケストレーションパターンが最もよく使われます
Python SDK では、次の 2 つのオーケストレーションパターンが最もよく登場します
| パターン | 仕組み | 最適な場 |
| パターン | 仕組み | 最適な場 |
| --- | --- | --- |
| Agents as tools | マネージャーエージェントが会話の制御を維持し、`Agent.as_tool()` を通じて専門エージェントを呼び出します。 | 1 つのエージェントに最終回答を担わせたい、複数の専門の出力を統合したい、または共通のガードレールを 1 か所で適用したい場合。 |
| ハンドオフ | トリアージエージェントが会話を専門エージェントへ振り分け、その専門エージェントがそのターンの残りでアクティブなエージェントになります。 | 専門エージェントに直接応答させたい、プロンプトを集中させたい、またはマネージャーが結果を説明せずに instructions を切り替えたい場合。 |
| Agents as tools | マネージャーエージェントが会話の制御を維持し、`Agent.as_tool()` を通じて専門エージェントを呼び出します。 | 1 つのエージェントに最終回答を担わせたい場合、複数の専門エージェントからの出力を統合したい場合、または共通のガードレールを 1 か所で適用したい場合。 |
| ハンドオフ | トリアージエージェントが会話を専門エージェントにルーティングし、その専門エージェントがそのターンの残りでアクティブなエージェントになります。 | 専門エージェントに直接応答させたい場合、プロンプトを焦点の絞られた状態に保ちたい場合、またはマネージャーが結果を説明することなく instructions を切り替えたい場合。 |
専門エージェントが限定的なサブタスクを支援すべき、ユーザー向け会話を引き継ぐべきではない場合は **agents as tools** を使ます。ルーティング自体がワークフローの一部であり、選ばれた専門エージェントに次のやり取りを担わせたい場合は **handoffs** を使ます。
専門エージェントが範囲の限定されたサブタスクを支援すべきだが、ユーザー向け会話を引き継ぐべきではない場合は **agents as tools** を使用します。ルーティング自体がワークフローの一部であり、選ばれた専門エージェントにインタラクションの次の部分を担わせたい場合は **ハンドオフ** を使用します。
2 つを組み合わせることもできます。トリアージエージェントが専門エージェントにハンドオフし、その専門エージェントがさらに限定的なサブタスクのために他のエージェントをツールとして呼び出すことも可能です。
この 2 つを組み合わせることもできます。トリアージエージェントが専門エージェントにハンドオフし、その専門エージェントがさらに狭いサブタスクのために他のエージェントをツールとして呼び出すこともできます。
このパターンは、タスクがオープンエンドで、LLM の知性に依存したい場合に非常に有効です。ここで最も重要な戦術は次のとおりです
このパターンは、タスクの自由度が高く、LLM の知能に頼りたい場合に最適です。ここで最も重要な戦術は次のとおりです
1. 良いプロンプトに投資する。どのツールが利用可能か、どう使うか、どのパラメーター範囲内で動作すべきかを明確にします。
2. アプリを監視し、反復改善す。どこで問題が起こるかを確認し、プロンプトを改善します。
3. エージェント内省と改善を許可する。たとえば、ループで実行して自己批評させる、またはエラーメッセージを与えて改善させます。
4. どんなタスクにも対応する汎用エージェントを期待するより、1 つのタスクに優れた専門エージェントを用意します。
5. [evals](https://platform.openai.com/docs/guides/evals) に投資す。これによりエージェントを改善するための訓練ができ、タスク性能を向上させられます。
1. 優れたプロンプトに投資します。利用できるツール、その使い方、そしてエージェントが従うべきパラメーターを明確にします。
2. アプリを監視し、反復改善します。どこで問題が起こるかを確認し、プロンプトを改善します。
3. エージェント内省して改善できるようにします。たとえば、ループで実行して自己批評させる、またはエラーメッセージを提供して改善させます。
4. 何でも得意であることを期待される汎用エージェントではなく、1 つのタスクに秀でた専門エージェントを用意します。
5. [evals](https://platform.openai.com/docs/guides/evals) に投資します。これによりエージェントをトレーニングして改善し、タスクの遂行能力を高めることができます。
このスタイルのオーケストレーションを支える SDK の基本コンポーネントを確認したい場合は、[tools](tools.md)、[handoffs](handoffs.md)、[running agents](running_agents.md) から始めてください。
このスタイルのオーケストレーションを支えるコア SDK の基本コンポーネントを知りたい場合は、[ツール](tools.md)、[ハンドオフ](handoffs.md)、[エージェントの実行](running_agents.md) から始めてください。
## コードによるオーケストレーション
LLM によるオーケストレーションは強力ですが、コードによるオーケストレーションは、速度コスト・性能の面でタスクをより決定的で予測可能にします。ここで一般的なパターンは次のとおりです
LLM によるオーケストレーションは強力ですが、コードによるオーケストレーションは、速度コスト、パフォーマンスの観点でタスクをより決定的で予測可能にします。ここで一般的なパターンは次のとおりです
- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使、コードで検査可能な適切な形式のデータを生成す。たとえば、タスクをいくつかのカテゴリーに分類するようエージェントに求め、そのカテゴリーに基づいて次のエージェントを選択できます。
- 1 つの出力を次の入力に変換して複数エージェントを連結する。ブログ記事執筆のようなタスクをリサーチ、アウトライン作成、記事執筆、批評、改善という一連のステップに分解できます。
- 評価とフィードバックを行うエージェントと組み合わせて、タスク実行エージェントを `while` ループ実行し、評価が出力が特定の基準を満たしたと言うまで続け
- 複数エージェントを並列実行す。たとえば `asyncio.gather` のような Python の基本機能を使います。これは、互依存しない複数タスクがある場合高速化に有用です。
- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使って、コードで検査できる適切な形式のデータを生成します。たとえば、エージェントにタスクをいくつかのカテゴリーに分類させ、そのカテゴリーに基づいて次のエージェントを選択できます。
- 複数のエージェントをチェーンし、あるエージェントの出力を次のエージェントの入力に変換します。ブログ記事を書くようなタスクを一連のステップに分解できます - リサーチする、アウトラインを書く、ブログ記事を書く、批評し、それから改善します。
- タスク実行するエージェントを `while` ループ内で、評価してフィードバックを提供するエージェントと一緒に実行し、評価が出力が特定の基準を満たしたと言うまで続けます
- 複数エージェントを並列実行します。たとえば`asyncio.gather` のような Python の基本コンポーネントを使います。これは、互いに依存しない複数タスクがある場合高速化に役立ちます。
[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) に多数のコード例があります。
[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) に多数のコード例があります。
## 関連ガイド
- 構成パターンとエージェント設定については [Agents](agents.md)
- `Agent.as_tool()` とマネージャースタイルのオーケストレーションについては [Tools](tools.md#agents-as-tools)。
- 専門エージェント間の委については [Handoffs](handoffs.md)
- 実行ごとのオーケストレーション制御と会話状態については [Running agents](running_agents.md)
- 最小のエンドツーエンドハンドオフ例については [Quickstart](quickstart.md)
- 構成パターンとエージェント設定については、[エージェント](agents.md) を参照してください
- `Agent.as_tool()` とマネージャースタイルのオーケストレーションについては、[ツール](tools.md#agents-as-tools) を参照してください
- 専門エージェント間の委については、[ハンドオフ](handoffs.md) を参照してください
- 実行ごとのオーケストレーション制御と会話状態については[エージェントの実行](running_agents.md) を参照してください
- 最小のエンドツーエンドハンドオフ例については、[クイックスタート](quickstart.md) を参照してください
+54 -27
View File
@@ -6,7 +6,7 @@ search:
## プロジェクトと仮想環境の作成
これを行うのは 1 回だけで十分です。
これは一度だけ行えば十分です。
```bash
mkdir my_project
@@ -16,12 +16,20 @@ python -m venv .venv
### 仮想環境の有効化
新しいターミナルセッションを開始するたびに、これを実行してください。
新しいターミナルセッションを開始するたびに行ってください。
macOS または Linux の場合:
```bash
source .venv/bin/activate
```
Windows の場合:
```cmd
.venv\Scripts\activate
```
### Agents SDK のインストール
```bash
@@ -30,15 +38,31 @@ pip install openai-agents # or `uv add openai-agents`, etc
### OpenAI API キーの設定
まだ持っていない場合は、OpenAI API キーを作成するために [こちらの手順](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)に従ってください。
まだ持っていない場合は、[こちらの手順](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)に従って OpenAI API キーを作成してください。
以下のコマンドは、現在のターミナルセッションにキーを設定します。
macOS または Linux の場合:
```bash
export OPENAI_API_KEY=sk-...
```
Windows PowerShell の場合:
```powershell
$env:OPENAI_API_KEY = "sk-..."
```
Windows コマンドプロンプトの場合:
```cmd
set "OPENAI_API_KEY=sk-..."
```
## 最初のエージェントの作成
エージェントは instructions、名前、および特定のモデルなどの任意の設定で定義されます。
エージェントはinstructions、名前、および特定のモデルなどの任意の設定で定義ます。
```python
from agents import Agent
@@ -70,21 +94,23 @@ if __name__ == "__main__":
asyncio.run(main())
```
2 回目のターンでは、`result.to_input_list()``Runner.run(...)` に戻して渡すか、[session](sessions/index.md) をアタッチするか、`conversation_id` / `previous_response_id` を使って OpenAI サーバー管理状態を再利用できます。[running agents](running_agents.md) ガイドでは、これらのアプローチを比較しています。
2 回目のターンでは、`result.to_input_list()``Runner.run(...)` に戻して渡すか、[セッション](sessions/index.md)をアタッチするか、`conversation_id` / `previous_response_id` OpenAI によりサーバー側で管理される状態を再利用できます。[エージェントの実行](running_agents.md)ガイドでは、これらのアプローチを比較しています。
目安として、次のルールを使ってください
次の目安を使ってください:
| こうしたい場合... | まず使うもの... |
| 実現したいこと... | まず使うもの... |
| --- | --- |
| 完全な手動制御とプロバイダー非依存の履歴 | `result.to_input_list()` |
| SDK に履歴の読み込みと保存を任せる | [`session=...`](sessions/index.md) |
| OpenAI 管理のサーバー側継続 | `previous_response_id` または `conversation_id` |
トレードオフと正確な挙動については、[Running agents](running_agents.md#choose-a-memory-strategy) を参照してください。
トレードオフと正確な挙動については、[エージェントの実行](running_agents.md#choose-a-memory-strategy)を参照してください。
タスクが主にプロンプト、ツール、会話状態で完結する場合は、シンプルな `Agent``Runner` を使います。エージェントが分離されたワークスペース内の実ファイルを検査または変更する必要がある場合は、[Sandbox エージェントのクイックスタート](sandbox_agents.md)に進んでください。
## エージェントへのツールの付与
情報を検索したりアクションを実行したりするためのツールを、エージェントに与えることができます。
エージェントにツールを与えることで、情報を調べたりアクションを実行したりできます。
```python
import asyncio
@@ -116,16 +142,16 @@ if __name__ == "__main__":
asyncio.run(main())
```
## 追加エージェントの作成
## さらにいくつかのエージェントの追加
マルチエージェントパターンを選ぶ前に、最終回答を誰が担うべきかを決めてください。
マルチエージェントパターンを選ぶ前に、最終回答の主導権を誰が持つべきかを決めてください。
- **ハンドオフ**: そのターンの該当部分について、専門担当が会話を引き継ぎます。
- **Agents as tools**: オーケストレーターが制御を維持し、専門担当をツールとして呼び出します。
- **ハンドオフ**: スペシャリストが、そのターンの該当部分について会話を引き継ぎます。
- **Agents as tools**: オーケストレーターが制御を維持し、スペシャリストをツールとして呼び出します。
このクイックスタートでは、最初の例として最も短いため **ハンドオフ** 続けて扱います。マネージャースタイルのパターンについては、[Agent orchestration](multi_agent.md) と [Tools: agents as tools](tools.md#agents-as-tools) を参照してください。
このクイックスタートでは、最初の例として最も短いため **ハンドオフ** 続けます。マネージャースタイルのパターンについては、[エージェントオーケストレーション](multi_agent.md)と[ツール: agents as tools](tools.md#agents-as-tools)を参照してください。
追加のエージェントも同じ方法で定義できます。`handoff_description` は、いつ委譲すかについてルーティングエージェントに追加のコンテキストを与えます。
追加のエージェントも同じ方法で定義できます。`handoff_description` は、いつ委譲すべきかについてルーティングエージェントに追加のコンテキストを提供します。
```python
from agents import Agent
@@ -145,7 +171,7 @@ math_tutor_agent = Agent(
## ハンドオフの定義
エージェントは、タスクを解決するに選択できる、外向きのハンドオフオプションの一覧を定義できます。
エージェントは、タスクを解決するに選択できるハンドオフ先の選択肢の一覧を定義できます。
```python
triage_agent = Agent(
@@ -157,7 +183,7 @@ triage_agent = Agent(
## エージェントオーケストレーションの実行
ランナーは、個々のエージェントの実行、あらゆるハンドオフ、およびあらゆるツール呼び出し処理を行います。
ランナーは、個々のエージェントの実行、すべてのハンドオフ、すべてのツール呼び出し処理ます。
```python
import asyncio
@@ -177,22 +203,23 @@ if __name__ == "__main__":
asyncio.run(main())
```
## 参コード例
## 参コード例
リポジトリには、同じ主要パターン完全なスクリプトが含まれています
このリポジトリには、同じ主要パターンに対応する完全なスクリプトが含まれています:
- 最初の実行用: [`examples/basic/hello_world.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/hello_world.py)
- 関数ツール用: [`examples/basic/tools.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/tools.py)
- マルチエージェントルーティング用: [`examples/agent_patterns/routing.py`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns/routing.py)
- [`examples/basic/hello_world.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/hello_world.py) は最初の実行の例です。
- [`examples/basic/tools.py`](https://github.com/openai/openai-agents-python/tree/main/examples/basic/tools.py) は関数ツールの例です。
- [`examples/agent_patterns/routing.py`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns/routing.py) はマルチエージェントルーティングの例です。
## トレースの表示
エージェント実行中に何が起きたかを確認するには、[OpenAI Dashboard の Trace viewer](https://platform.openai.com/traces) に移動して、エージェント実行のトレースを表示してください。
エージェント実行中に何が起きたかを確認するには、[OpenAI ダッシュボードのトレースビューアー](https://platform.openai.com/traces)に移動して、エージェント実行のトレースを表示してください。
## 次のステップ
より複雑な agentic フローの構築方法を学びましょう
より複雑なエージェント型フローの構築方法を学びましょう:
- [Agents](agents.md) の設定方法を学ぶ
- [running agents](running_agents.md) と [sessions](sessions/index.md) について学
- [tools](tools.md)、[guardrails](guardrails.md)、[models](models/index.md) について学ぶ。
- [エージェント](agents.md)の設定方法について学びます
- [エージェントの実行](running_agents.md)と[セッション](sessions/index.md)について学びます
- 作業を実際のワークスペース内で行う必要がある場合は、[Sandbox エージェント](sandbox_agents.md)について学びます。
- [ツール](tools.md)、[ガードレール](guardrails.md)、[モデル](models/index.md)について学びます。
+76 -71
View File
@@ -4,59 +4,55 @@ search:
---
# Realtime エージェントガイド
このガイドでは、 OpenAI Agents SDK の realtime レイヤーが OpenAI Realtime API にどのように対応しているか、そして Python SDK がその上にどのような追加動作を加えるかを説明します。
このガイドでは、 OpenAI Agents SDK の realtime レイヤーが OpenAI Realtime API にどのように対応するか、および Python SDK がその上に追加する挙動について説明します。
!!! warning "Beta 機能"
!!! note "はじめに"
Realtime エージェントは beta 段階です。実装の改善に伴い、破壊的変更が入る可能性があります
!!! note "開始ポイント"
デフォルトの Python パスを使いたい場合は、まず [quickstart](quickstart.md) を読んでください。アプリでサーバーサイド WebSocket と SIP のどちらを使うべきか判断したい場合は、[Realtime transport](transport.md) を読んでください。ブラウザの WebRTC transport は Python SDK の対象外です。
デフォルトの Python パスを使いたい場合は、まず [クイックスタート](quickstart.md) を読んでください。アプリでサーバー側 WebSocket または SIP のどちらを使うべきかを判断している場合は、 [Realtime トランスポート](transport.md) を読んでください。ブラウザー WebRTC トランスポートは Python SDK には含まれていません
## 概要
Realtime エージェントは Realtime API への長時間接続を維持するため、モデルはテキストと音声を段階的に処理し、音声出力をストリーミングし、ツールを呼び出し、毎ターン新しいリクエストを再開せずに割り込みを処理できます
Realtime エージェントは Realtime API への長寿命の接続を開いたままにするため、モデルはテキストと音声を段階的に処理し、音声出力をストリーミングし、ツールを呼び出し、中断を処理できます。ターンごとに新しいリクエストを再開始する必要はありません
主な SDK コンポーネントは次のとおりです。
- **RealtimeAgent**: 1 つの realtime 専門エージェント向けの instructions、ツール、出力ガードレール、ハンドオフ
- **RealtimeRunner**: 開始エージェントを realtime transport に接続するセッションファクトリ
- **RealtimeSession**: 入力送信、イベント受信、履歴追跡、ツール実行を行うライブセッション
- **RealtimeModel**: transport 抽象化。デフォルトは OpenAI のサーバーサイド WebSocket 実装です。
- **RealtimeAgent**: 1 つの realtime 専門エージェント向けの instructions、tools、出力ガードレール、ハンドオフ
- **RealtimeRunner**: 開始エージェントを realtime トランスポートに接続するセッションファクトリ
- **RealtimeSession**: 入力送信、イベント受信、履歴追跡、ツール実行するライブセッション
- **RealtimeModel**: トランスポート抽象化。デフォルトは OpenAI のサーバー WebSocket 実装です。
## セッションライフサイクル
典型的な realtime セッションは次のようになります。
一般的な realtime セッションは次のようになります。
1. 1 つ以上の `RealtimeAgent` を作成します。
2. 開始エージェント `RealtimeRunner` を作成します。
2. 開始エージェントを指定して `RealtimeRunner` を作成します。
3. `await runner.run()` を呼び出して `RealtimeSession` を取得します。
4. `async with session:` または `await session.enter()` でセッションに入ります。
5. `send_message()` または `send_audio()` でユーザー入力を送信します。
6. 会話が終了するまでセッションイベントを反復処理します。
テキスト専用 run とは異なり、`runner.run()` は最終 result を即時には生成しません。transport レイヤーと同期を保ちながら、ローカル履歴、バックグラウンドツール実行、ガードレール状態、アクティブなエージェント設定を保持するライブセッションオブジェクトを返します。
テキストのみの実行とは異なり、 `runner.run()` は最終的な実行結果をすぐには生成しません。ローカル履歴、バックグラウンドでのツール実行、ガードレール状態、アクティブなエージェント設定をトランスポート層と同期し続けるライブセッションオブジェクトを返します。
デフォルトでは、`RealtimeRunner``OpenAIRealtimeWebSocketModel` を使用します。そのため、デフォルトの Python パスは Realtime API へのサーバーサイド WebSocket 接続です。別の `RealtimeModel` を渡した場合でも、同じセッションライフサイクルとエージェント機能が適用され、接続メカニズムのみ変更できます。
デフォルトでは、 `RealtimeRunner``OpenAIRealtimeWebSocketModel` を使用するため、デフォルトの Python パスは Realtime API へのサーバー WebSocket 接続です。別の `RealtimeModel` を渡した場合でも、接続の仕組みは変わる可能性がありますが、同じセッションライフサイクルとエージェント機能が引き続き適用されます。
## エージェントとセッション設定
`RealtimeAgent` は通常の `Agent` 型より意図的に範囲が狭くなっています。
`RealtimeAgent` は通常の `Agent` 型より意図的に機能範囲が絞られています。
- モデル選択はエージェントごとではなくセッションレベルで設定ます。
- structured outputs はサポートされていません。
- Voice は設定できますが、セッションがすでに音声を生成した後は変更できません。
- Instructions、関数ツール、ハンドオフ、フック、出力ガードレールはすべて引き続き利用できます。
- モデル選択はエージェントごとではなくセッションレベルで設定されます。
- Structured outputs はサポートされていません。
- voice は設定できますが、セッションがすでに発話音声を生成した後は変更できません。
- instructions、関数ツール、ハンドオフ、フック、出力ガードレールはすべて引き続き機能します。
`RealtimeSessionModelSettings` は、新しいネストされた `audio` 設定と古いフラットなエイリアスの両方をサポートします。新コードではネスト形式を推奨し、新しい realtime エージェント`gpt-realtime-1.5` から始めてください。
`RealtimeSessionModelSettings` は、新しいネストされた `audio` 設定と古いフラットなエイリアスの両方をサポートします。新しいコードではネストされた形式を推奨し、新しい realtime エージェント`gpt-realtime-2.1` から始めてください。
```python
runner = RealtimeRunner(
starting_agent=agent,
config={
"model_settings": {
"model_name": "gpt-realtime-1.5",
"model_name": "gpt-realtime-2.1",
"audio": {
"input": {
"format": "pcm16",
@@ -71,7 +67,7 @@ runner = RealtimeRunner(
)
```
有用なセッションレベル設定には次が含まれます。
有用なセッションレベル設定には次のものがあります。
- `audio.input.format`, `audio.output.format`
- `audio.input.transcription`
@@ -83,7 +79,7 @@ runner = RealtimeRunner(
- `prompt`
- `tracing`
`RealtimeRunner(config=...)` の有用な run レベル設定には次が含まれます。
`RealtimeRunner(config=...)` の有用な run レベル設定には次のものがあります。
- `async_tool_calls`
- `output_guardrails`
@@ -91,13 +87,13 @@ runner = RealtimeRunner(
- `tool_error_formatter`
- `tracing_disabled`
型付きの完全な仕様は [`RealtimeRunConfig`][agents.realtime.config.RealtimeRunConfig] と [`RealtimeSessionModelSettings`][agents.realtime.config.RealtimeSessionModelSettings] を参照してください。
完全な型付きインターフェースについては、 [`RealtimeRunConfig`][agents.realtime.config.RealtimeRunConfig] と [`RealtimeSessionModelSettings`][agents.realtime.config.RealtimeSessionModelSettings] を参照してください。
## 入力と出力
### テキストと構造化ユーザーメッセージ
プレーンテキストまたは構造化 realtime メッセージには [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] を使用します。
プレーンテキストまたは構造化された realtime メッセージには [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] を使用します。
```python
from agents.realtime import RealtimeUserInputMessage
@@ -115,31 +111,31 @@ message: RealtimeUserInputMessage = {
await session.send_message(message)
```
構造化メッセージは、realtime 会話に画像入力を含める主な方法です。[`examples/realtime/app/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/app/server.py) の Web デモでは、この方法で `input_image` メッセージを転送しています。
構造化メッセージは、 realtime 会話に画像入力を含める主な方法です。 [`examples/realtime/app/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/app/server.py) のサンプル Web デモでは、この方法で `input_image` メッセージを転送しています。
### 音声入力
raw 音声バイトをストリーミングするには [`session.send_audio()`][agents.realtime.session.RealtimeSession.send_audio] を使用します。
生の音声バイトをストリーミングするには [`session.send_audio()`][agents.realtime.session.RealtimeSession.send_audio] を使用します。
```python
await session.send_audio(audio_bytes)
```
サーバーサイドの turn detection が無効な場合、ターン境界の指定はユーザー側の責任です。高レベルの簡易手段は次のとおりです。
サーバー側のターン検出が無効な場合、ターン境界をマークする責任は開発者側にあります。高レベルの便利な方法は次のとおりです。
```python
await session.send_audio(audio_bytes, commit=True)
```
より低レベル制御が必要な場合は、基盤となる model transport を通じて `input_audio_buffer.commit` などの raw client event も送信できます。
より低レベル制御が必要な場合は、基盤となるモデルトランスポートを通じて `input_audio_buffer.commit` などの raw クライアントイベントを送信することもできます。
### 手動レスポンス制御
### 手動応答制御
`session.send_message()` は高レベルパスユーザー入力を送信し、レスポンス開始も自動で行います。raw 音声バッファリングは、すべての設定で同様に自動実行される **わけではありません**
`session.send_message()` は高レベルパスを使ってユーザー入力を送信し、応答を開始します。生の音声バッファリングは、すべての設定で同じことを自動的に行うわけでは **ありません**
Realtime API レベルでは、手動ターン制御 raw `session.update``turn_detection` をクリアし、その後 `input_audio_buffer.commit``response.create` を自分で送信することを意味します。
Realtime API レベルでは、手動ターン制御とは、 raw `session.update``turn_detection` をクリアし、その後 `input_audio_buffer.commit``response.create` を自分で送信することを意味します。
ターンを手動管理る場合は、model transport 経由で raw client event を送信できます。
ターンを手動管理している場合は、モデルのトランスポートを通じて raw クライアントイベントを送信できます。
```python
from agents.realtime.model_inputs import RealtimeModelSendRawMessage
@@ -155,17 +151,17 @@ await session.model.send_event(
このパターンは次の場合に有用です。
- `turn_detection` が無効で、モデルがいつ応答すかを自分で決めたい場合
- レスポンスをトリガーする前にユーザー入力を検査またはゲートしたい場合
- out-of-band レスポンス向けにカスタムプロンプトが必要な場合
- `turn_detection` が無効で、モデルがいつ応答すべきかを自分で決めたい場合
- 応答をトリガーする前にユーザー入力を検査またはゲートしたい場合
- アウトオブバンド応答にカスタムプロンプトが必要な場合
[`examples/realtime/twilio_sip/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip/server.py) の SIP 例では、raw `response.create` を使って開始時の挨拶を強制しています。
[`examples/realtime/twilio_sip/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip/server.py) の SIP 例では、開始時の挨拶を強制するために raw `response.create` を使しています。
## イベント、履歴、割り込み
## イベント、履歴、中断
`RealtimeSession` は高レベル SDK イベントを発行しつつ、必要時には raw model event も転送します。
`RealtimeSession`、必要なときには raw モデルイベントも転送しつつ、より高レベル SDK イベントを発行します。
価値の高いセッションイベントには次が含まれます。
有用性の高いセッションイベントには次のものがあります。
- `audio`, `audio_end`, `audio_interrupted`
- `agent_start`, `agent_end`
@@ -177,21 +173,21 @@ await session.model.send_event(
- `error`
- `raw_model_event`
UI 状態管理で特に有用なのは通常 `history_added``history_updated` です。これらは、ユーザーメッセージ、assistant メッセージ、ツール呼び出しを含むセッションのローカル履歴を `RealtimeItem` オブジェクトとして公開します。
UI 状態に最も有用なイベントは通常 `history_added``history_updated` です。これらは、ユーザーメッセージ、アシスタントメッセージ、ツール呼び出しを含むセッションのローカル履歴を `RealtimeItem` オブジェクトとして公開します。
### 割り込みと再生追跡
### 中断と再生トラッキング
ユーザーが assistant を割り込んだ場合、セッションは `audio_interrupted` を発行し、サーバーサイド会話がユーザー実際の聴取内容と一致するよう履歴を更新します。
ユーザーがアシスタントを中断すると、セッションは `audio_interrupted` を発行し、履歴を更新して、サーバー側の会話がユーザー実際に聞いた内容と一致し続けるようにします。
遅延のローカル再生では、デフォルトの再生トラッカーで十分なことが多いです。リモート再生や遅延再生のシナリオ、特に電話では、すべての生成音声がすでに聴取済みと仮定するのではなく、実際の再生進捗に基づいて割り込み切り詰めを行うために [`RealtimePlaybackTracker`][agents.realtime.model.RealtimePlaybackTracker] を使用してください。
レイテンシーのローカル再生では、デフォルトの再生トラッカーで十分なことが多いです。リモート再生や遅延再生のシナリオ、特にテレフォニーでは、 [`RealtimePlaybackTracker`][agents.realtime.model.RealtimePlaybackTracker] を使用してください。これにより、生成された音声がすべてすでに聞かれたと仮定するのではなく、実際の再生進行に基づいて中断時の切り詰めが行われます。
[`examples/realtime/twilio/twilio_handler.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio/twilio_handler.py) の Twilio 例はこのパターンを示しています。
[`examples/realtime/twilio/twilio_handler.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio/twilio_handler.py) の Twilio 例はこのパターンを示しています。
## ツール、承認、ハンドオフ、ガードレール
### 関数ツール
Realtime エージェントはライブ会話中関数ツールをサポートします。
Realtime エージェントはライブ会話中関数ツールをサポートします。
```python
from agents import function_tool
@@ -212,7 +208,9 @@ agent = RealtimeAgent(
### ツール承認
関数ツールは実行前に人間の承認を必要とするようにできます。その場合、セッションは `tool_approval_required` を発行し、`approve_tool_call()` または `reject_tool_call()` を呼び出すまでツール実行を一時停止します。
関数ツールは実行前に人間の承認を要求できます。その場合、セッションは `tool_approval_required` を発行し、 `approve_tool_call()` または `reject_tool_call()` を呼び出すまでツール実行を一時停止します。
ツールに入力ガードレールもある場合、それらのガードレールは承認後、実行の直前に実行されます。承認イベントが発行される前にそれらを実行するには、 `RealtimeRunner(..., config={"tool_execution": {"pre_approval_tool_input_guardrails": True}})` で runner を作成します。この事前承認チェックに合格した呼び出しも、承認後、実行前にもう一度チェックされます。
```python
async for event in session:
@@ -220,11 +218,11 @@ async for event in session:
await session.approve_tool_call(event.call_id)
```
具体的なサーバーサイド承認ループ [`examples/realtime/app/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/app/server.py) を参照してください。human-in-the-loop ドキュメントも [Human in the loop](../human_in_the_loop.md) でこのフローを参照しています。
具体的なサーバー承認ループについては、 [`examples/realtime/app/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/app/server.py) を参照してください。人間参加型のドキュメントも [人間を介した処理](../human_in_the_loop.md) でこのフローを参照しています。
### ハンドオフ
Realtime ハンドオフでは、あるエージェントがライブ会話を別の専門エージェントへ転送できます。
Realtime ハンドオフにより、 1 つのエージェントがライブ会話を別の専門エージェントへ転送できます。
```python
from agents.realtime import RealtimeAgent, realtime_handoff
@@ -237,15 +235,20 @@ billing_agent = RealtimeAgent(
main_agent = RealtimeAgent(
name="Customer Service",
instructions="Triage the request and hand off when needed.",
handoffs=[realtime_handoff(billing_agent, tool_description="Transfer to billing support")],
handoffs=[
realtime_handoff(
billing_agent,
tool_description_override="Transfer to billing support",
)
],
)
```
`RealtimeAgent` ハンドオフは自動ラップされ、`realtime_handoff(...)` では名前、説明、検証、コールバック、可用性をカスタマイズできます。Realtime ハンドオフは通常の handoff `input_filter` をサポートしません。
そのまま`RealtimeAgent` ハンドオフは自動的にラップされ、 `realtime_handoff(...)` では名前、説明、検証、コールバック、利用可否をカスタマイズできます。Realtime ハンドオフは通常のハンドオフの `input_filter` **サポートしていません**
### ガードレール
Realtime エージェントでサポートされるのは出力ガードレールのみです。これらは各部分 token ごとではなく、デバウンスされた transcript 蓄積に対して実行され、例外を送出する代わりに `guardrail_tripped` を発行します。
Realtime エージェントは、エージェント応答に対する出力ガードレールと、関数ツール呼び出しに対する入力ガードレールをサポートします。出力ガードレールは、部分的なトークンごとではなく、デバウンスされたトランスクリプトの蓄積に対して実行され、例外を発生させる代わりに `guardrail_tripped` を発行します。
```python
from agents.guardrail import GuardrailFunctionOutput, OutputGuardrail
@@ -265,11 +268,13 @@ agent = RealtimeAgent(
)
```
realtime 出力ガードレールが作動すると、セッションはアクティブな応答を中断し、 `response.cancel` を強制し、 `guardrail_tripped` を発行し、作動したガードレールの名前を示す後続のユーザーメッセージを送信して、モデルが代替応答を生成できるようにします。音声プレーヤーはそれでも `audio_interrupted` をリッスンし、ローカル再生をただちに停止する必要があります。これは、ガードレールがデバウンスされたトランスクリプトテキストに対して実行され、トリップワイヤーが作動した時点で一部の音声がすでにバッファリングされている可能性があるためです。
## SIP とテレフォニー
Python SDK には [`OpenAIRealtimeSIPModel`][agents.realtime.openai_realtime.OpenAIRealtimeSIPModel] による第一級の SIP 接続フローが含まれています。
Python SDK には [`OpenAIRealtimeSIPModel`][agents.realtime.openai_realtime.OpenAIRealtimeSIPModel] を介したファーストクラスの SIP アタッチフローが含まれています。
Realtime Calls API 経由で着信し、結果として得られ `call_id` にエージェントセッションを接続したい場合に使用します。
Realtime Calls API 経由で通話が到着し、得られ `call_id` にエージェントセッションをアタッチしたい場合に使用します。
```python
from agents.realtime import RealtimeRunner
@@ -286,18 +291,18 @@ async with await runner.run(
...
```
まず通話を受け付ける必要があり、受け付けペイロードをエージェント由来のセッション設定一致させたい場合は、`OpenAIRealtimeSIPModel.build_initial_session_payload(...)` を使用してください。完全なフローは [`examples/realtime/twilio_sip/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip/server.py) にあります。
先に通話を受け付ける必要があり、 accept ペイロードをエージェント由来のセッション設定一致させたい場合は、 `OpenAIRealtimeSIPModel.build_initial_session_payload(...)` を使用します。完全なフローは [`examples/realtime/twilio_sip/server.py`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip/server.py) に示されています。
## 低レベルアクセスとカスタムエンドポイント
`session.model` から基盤 transport オブジェクトにアクセスできます。
`session.model` を通じて基盤となるトランスポートオブジェクトにアクセスできます。
必要な場合に使用します。
次が必要な場合に使用します。
- `session.model.add_listener(...)` によるカスタムリスナー
- `response.create``session.update` などの raw client event
- `model_config` 経由のカスタム `url``headers``api_key` 処理
- 既存 realtime 通話への `call_id` 接続
- `response.create``session.update` などの raw クライアントイベント
- `model_config` によるカスタム `url` `headers` `api_key` 処理
- 既存 realtime 通話への `call_id` アタッチ
`RealtimeModelConfig` は次をサポートします。
@@ -308,9 +313,9 @@ async with await runner.run(
- `playback_tracker`
- `call_id`
このリポジトリに含まれ`call_id` の例は SIP です。より広 Realtime API で一部のサーバーサイド制御フローに `call_id` を使ますが、ここでは Python 例としては提供されていません。
このリポジトリに同梱されてい`call_id`コード例は SIP です。より広範な Realtime API でも、一部のサーバー制御フローに `call_id` を使用しますが、それらはここでは Python のコード例としてパッケージ化されていません。
Azure OpenAI に接続する場合は、 GA Realtime endpoint URL と明示的な headers を渡してください。例:
Azure OpenAI に接続する場合は、 GA Realtime エンドポイント URL と明示的なヘッダーを渡します。例:
```python
session = await runner.run(
@@ -321,7 +326,7 @@ session = await runner.run(
)
```
トークンベース認証では、`headers`bearer token を使用します。
トークンベース認証では、 `headers`Bearer トークンを使用します。
```python
session = await runner.run(
@@ -332,12 +337,12 @@ session = await runner.run(
)
```
`headers` を渡した場合、SDK は `Authorization` を自動追加しません。realtime エージェントではレガシー beta パス`/openai/realtime?api-version=...`)を避けてください。
`headers` を渡すと、 SDK は `Authorization` を自動的には追加しません。realtime エージェントでは、従来の beta パス (`/openai/realtime?api-version=...`) は避けてください。
## 参考資料
## 関連資料
- [Realtime transport](transport.md)
- [Quickstart](quickstart.md)
- [OpenAI Realtime conversations](https://developers.openai.com/api/docs/guides/realtime-conversations/)
- [OpenAI Realtime server-side controls](https://developers.openai.com/api/docs/guides/realtime-server-controls/)
- [Realtime トランスポート](transport.md)
- [クイックスタート](quickstart.md)
- [OpenAI Realtime 会話](https://developers.openai.com/api/docs/guides/realtime-conversations/)
- [OpenAI Realtime サーバー側コントロール](https://developers.openai.com/api/docs/guides/realtime-server-controls/)
- [`examples/realtime`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime)
+33 -37
View File
@@ -4,33 +4,29 @@ search:
---
# クイックスタート
Python SDK の Realtime エージェントは、WebSocket トランスポート経由の OpenAI Realtime API 上に構築された、サーバーサイドの低レイテンシエージェントです。
Python SDK のリアルタイムエージェントは、WebSocket トランスポート経由の OpenAI Realtime API 上に構築された、サーバーの低レイテンシエージェントです。
!!! warning "Beta 機能"
!!! note "Python SDK の境界"
Realtime エージェントは beta です。実装の改善に伴い、破壊的変更が発生する可能性があります
!!! note "Python SDK の範囲"
Python SDK はブラウザー向けの WebRTC トランスポートを **提供しません** 。このページでは、サーバーサイド WebSocket 経由で Python が管理する realtime session のみを扱います。サーバーサイドのオーケストレーション、ツール、承認、テレフォニー統合にはこの SDK を使用してください。あわせて [Realtime transport](transport.md) も参照してください。
Python SDK は、ブラウザーの WebRTC トランスポートを **提供していません** 。このページでは、サーバー側 WebSocket を介して Python で管理されるリアルタイムセッションのみを扱います。この SDK は、サーバー側のオーケストレーション、ツール、承認、テレフォニー連携に使用してください。併せて [リアルタイムトランスポート](transport.md) も参照してください
## 前提条件
- Python 3.10 以上
- OpenAI API キー
- OpenAI Agents SDK の基本的な理解
- OpenAI Agents SDK の基本的な知識
## インストール
まだ場合は、OpenAI Agents SDK をインストールします。
まだインストールしていない場合は、OpenAI Agents SDK をインストールしてください:
```bash
pip install openai-agents
```
## サーバーサイド realtime session の作成
## サーバー側リアルタイムセッションの作成
### 1. Realtime コンポーネントのインポート
### 1. リアルタイムコンポーネントのインポート
```python
import asyncio
@@ -47,16 +43,16 @@ agent = RealtimeAgent(
)
```
### 3. runner の設定
### 3. ランナーの設定
新しいコードでは、ネストされた `audio.input` / `audio.output` session 設定形式を推奨します。新しい Realtime エージェントでは、`gpt-realtime-1.5` から始めてください。
新しいコードでは、ネストされた `audio.input` / `audio.output` のセッション設定形式を推奨します。新しいリアルタイムエージェントでは、`gpt-realtime-2.1` から始めてください。
```python
runner = RealtimeRunner(
starting_agent=agent,
config={
"model_settings": {
"model_name": "gpt-realtime-1.5",
"model_name": "gpt-realtime-2.1",
"audio": {
"input": {
"format": "pcm16",
@@ -76,9 +72,9 @@ runner = RealtimeRunner(
)
```
### 4. session の開始と入力の送信
### 4. セッションの開始と入力の送信
`runner.run()``RealtimeSession` を返します。session context に入ると接続が開かれます。
`runner.run()``RealtimeSession` を返します。セッションコンテキストに入ると接続が開かれます。
```python
async def main() -> None:
@@ -104,59 +100,59 @@ if __name__ == "__main__":
asyncio.run(main())
```
`session.send_message()` はプレーン文字列または構造化された realtime message のいずれかを受け取ります。raw audio chunk には [`session.send_audio()`][agents.realtime.session.RealtimeSession.send_audio] を使用してください。
`session.send_message()`プレーン文字列または構造化されたリアルタイムメッセージのいずれかを受け取ります。生の音声チャンクには[`session.send_audio()`][agents.realtime.session.RealtimeSession.send_audio] を使用してください。
## このクイックスタートに含まれない内容
- マイク入力とスピーカー再生のコード。[`examples/realtime`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) の realtime コード例を参照してください。
- SIP / テレフォニー接続フロー。[Realtime transport](transport.md) と [SIP セクション](guide.md#sip-and-telephony) を参照してください。
- マイクのキャプチャおよびスピーカー再生のコード。[`examples/realtime`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) のリアルタイムのコード例を参照してください。
- SIP / テレフォニーのアタッチフロー。[リアルタイムトランスポート](transport.md) と [SIP セクション](guide.md#sip-and-telephony) を参照してください。
## 主要設定
基本的な session が動作したら、次によく使われる設定は以下です
基本的なセッションが動作するようになったら、多くの方が次に利用する設定は次のとおりです:
- `model_name`
- `audio.input.format`, `audio.output.format`
- `audio.input.transcription`
- `audio.input.noise_reduction`
- 自動ターン検出のための `audio.input.turn_detection`
- `audio.input.turn_detection`(自動ターン検出用)
- `audio.output.voice`
- `tool_choice`, `prompt`, `tracing`
- `async_tool_calls`, `guardrails_settings.debounce_text_length`, `tool_error_formatter`
- `async_tool_calls`, `tool_execution.pre_approval_tool_input_guardrails`, `guardrails_settings.debounce_text_length`, `tool_error_formatter`
`input_audio_format``output_audio_format``input_audio_transcription``turn_detection` などの古いフラットな別名も引き続き動作しますが、新しいコードではネストされた `audio` 設定推奨ます。
`input_audio_format``output_audio_format``input_audio_transcription``turn_detection` などの古いフラットなエイリアスも引き続き機能しますが、新しいコードではネストされた `audio` 設定推奨されます。
手動ターン制御を行う場合は、[Realtime agents guide](guide.md#manual-response-control) にある説明のとおり、raw `session.update` / `input_audio_buffer.commit` / `response.create` フローを使用してください。
手動ターン制御には、[リアルタイムエージェントガイド](guide.md#manual-response-control) で説明されている raw `session.update` / `input_audio_buffer.commit` / `response.create` フローを使用してください。
完全なスキーマについては、[`RealtimeRunConfig`][agents.realtime.config.RealtimeRunConfig] [`RealtimeSessionModelSettings`][agents.realtime.config.RealtimeSessionModelSettings] を参照してください。
完全なスキーマについては、[`RealtimeRunConfig`][agents.realtime.config.RealtimeRunConfig] および [`RealtimeSessionModelSettings`][agents.realtime.config.RealtimeSessionModelSettings] を参照してください。
## 接続オプション
環境変数に API キーを設定します。
API キーを環境変数に設定してください:
```bash
export OPENAI_API_KEY="your-api-key-here"
```
または、session 開始時に直接渡します
または、セッションの開始時に直接渡します:
```python
session = await runner.run(model_config={"api_key": "your-api-key"})
```
`model_config`次もサポートします
`model_config`以下にも対応しています:
- `url`: カスタム WebSocket endpoint
- `headers`: カスタム request header
- `call_id`: 既存の realtime call に接続します。このリポジトリで文書化されている接続フローは SIP です。
- `playback_tracker`: ユーザーが実際に聞いた audio の量を報告します
- `url`: カスタム WebSocket エンドポイント
- `headers`: カスタムリクエストヘッダー
- `call_id`: 既存のリアルタイムコールにアタッチします。このリポジトリでドキュメント化されているアタッチフローは SIP です。
- `playback_tracker`: ユーザーが実際に聞いた音声量を報告します
`headers` を明示的に渡した場合、SDK は `Authorization` header **自動挿入しません**
`headers` を明示的に渡場合、SDK は `Authorization` ヘッダー**挿入しません**
Azure OpenAI に接続する場合は、`model_config["url"]` に GA Realtime endpoint URL と明示的な headers を渡してください。realtime エージェントでは、legacy beta path (`/openai/realtime?api-version=...`) を避けてください。詳細は [Realtime agents guide](guide.md#low-level-access-and-custom-endpoints) を参照してください。
Azure OpenAI に接続する場合は、`model_config["url"]` に GA Realtime エンドポイント URL を指定し、明示的なヘッダーも渡してください。リアルタイムエージェントでは、レガシーな beta パス(`/openai/realtime?api-version=...`)の使用は避けてください。詳細については、[リアルタイムエージェントガイド](guide.md#low-level-access-and-custom-endpoints) を参照してください。
## 次のステップ
- サーバーサイド WebSocket と SIP のどちらを選ぶか判断するために [Realtime transport](transport.md) を読んでください。
- ライフサイクル、構造化入力、承認、ハンドオフ、ガードレール、低レベル制御について [Realtime agents guide](guide.md) を読んでください。
- [`examples/realtime`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) のコード例を確認してください。
- サーバー WebSocket と SIP のどちらを選ぶか判断するには、[リアルタイムトランスポート](transport.md) をお読みください。
- ライフサイクル、構造化入力、承認、ハンドオフ、ガードレール、低レベル制御については、[リアルタイムエージェントガイド](guide.md) をお読みください。
- [`examples/realtime`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) のコード例をご覧ください。
+27 -27
View File
@@ -4,32 +4,32 @@ search:
---
# Realtime トランスポート
このページは、realtime エージェントを Python アプリケーションにどのように組み込むかを判断するために使用します
このページは、realtime エージェントを Python アプリケーションにどのように組み込むかを判断するために使用してください
!!! note "Python SDK の境界"
Python SDK にはブラウザー WebRTC トランスポートは **含まれていません** 。このページは Python SDK のトランスポート選択、つまりサーバーサイド WebSocket と SIP アタッチフローのみを対象としています。ブラウザー WebRTC は別のプラットフォームトピックであり、公式の [Realtime API with WebRTC](https://developers.openai.com/api/docs/guides/realtime-webrtc/) ガイドに記載されています。
Python SDK にはブラウザー WebRTC トランスポートは含まれて **いません**。このページはPython SDK のトランスポート選択肢であるサーバー WebSocket と SIP アタッチフローのみをいます。ブラウザー WebRTC は別のプラットフォームトピックであり、公式の [WebRTC による Realtime API](https://developers.openai.com/api/docs/guides/realtime-webrtc/) ガイドに記載されています。
## 判断ガイド
| Goal | Start with | Why |
| 目的 | はじめに | 理由 |
| --- | --- | --- |
| サーバー管理の realtime アプリを構築する | [Quickstart](quickstart.md) | デフォルトの Python パスは、`RealtimeRunner` 管理されるサーバーサイド WebSocket セッションです。 |
| どのトランスポートとデプロイ形状を選ぶべきか理解する | このページ | トランスポートやデプロイ形状を確定する前に、このページを使用してください。 |
| エージェントを電話または SIP 通話にアタッチする | [Realtime guide](guide.md) と [`examples/realtime/twilio_sip`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip) | このリポジトリには、`call_id` で駆動する SIP アタッチフローが含まれています。 |
| サーバー管理の realtime アプリを構築する | [クイックスタート](quickstart.md) | デフォルトの Python パスは、`RealtimeRunner` によって管理されるサーバー WebSocket セッションです。 |
| 選択すべきトランスポートとデプロイ形態を理解する | このページ | トランスポートやデプロイ形態を決定する前に使用してください。 |
| エージェントを電話または SIP 通話にアタッチする | [Realtime ガイド](guide.md) と [`examples/realtime/twilio_sip`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip) | このリポジトリには、`call_id` によって駆動される SIP アタッチフローが含まれています。 |
## サーバーサイド WebSocket というデフォルトの Python パス
## デフォルトの Python パスであるサーバー側 WebSocket
`RealtimeRunner` は、カスタム `RealtimeModel` を渡さない限り `OpenAIRealtimeWebSocketModel` を使用します。
カスタム `RealtimeModel` を渡さない限り`RealtimeRunner` `OpenAIRealtimeWebSocketModel` を使用します。
つまり、標準的な Python トポロジーは次のようになります。
1. Python サービスが `RealtimeRunner` を作成します。
2. `await runner.run()` `RealtimeSession` を返します。
2. `await runner.run()` `RealtimeSession` を返します。
3. セッションに入り、テキスト、構造化メッセージ、または音声を送信します。
4. `RealtimeSessionEvent` 項目を消費し、音声またはトランスクリプトをアプリケーションに転送します。
のトポロジーは、コアデモアプリ、CLI 例、Twilio Media Streams 例で使用されていす。
は、コアデモアプリ、CLI 例、Twilio Media Streams 例で使用されているトポロジーです。
- [`examples/realtime/app`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/app)
- [`examples/realtime/cli`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/cli)
@@ -37,40 +37,40 @@ search:
サーバーが音声パイプライン、ツール実行、承認フロー、履歴処理を管理する場合は、このパスを使用してください。
## SIP アタッチというテレフォニーパス
## テレフォニー向けパスとしての SIP アタッチ
このリポジトリで文書化されているテレフォニーフローでは、Python SDK は `call_id` を介して既存の realtime 通話にアタッチします。
このリポジトリで説明されているテレフォニーフローでは、Python SDK は `call_id` を介して既存の realtime 通話にアタッチします。
このトポロジーは次のようになります。
1. OpenAI が `realtime.call.incoming` などの webhook をサービスに送信します。
2. サービスが Realtime Calls API を通じて通話を受け付けます。
2. サービスが Realtime Calls API を通じて通話を受け入れます。
3. Python サービスが `RealtimeRunner(..., model=OpenAIRealtimeSIPModel())` を開始します。
4. セッションは `model_config={"call_id": ...}` で接続し、その後は他の realtime セッションと同様にイベントを処理します。
これは [`examples/realtime/twilio_sip`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip) 示されているトポロジーです。
これは [`examples/realtime/twilio_sip`](https://github.com/openai/openai-agents-python/tree/main/examples/realtime/twilio_sip) 示されているトポロジーです。
より広 Realtime API でも一部のサーバーサイド制御パターンで `call_id` を使用しますが、このリポジトリで提供されているアタッチ例は SIP です。
より広範な Realtime API でも一部のサーバー制御パターンで `call_id` を使用しますが、このリポジトリに含まれるアタッチ例は SIP です。
## この SDK の対象外であるブラウザー WebRTC
## この SDK の範囲外であるブラウザー WebRTC
アプリの主クライアントが Realtime WebRTC を使用するブラウザーである場合:
アプリの主クライアントが Realtime WebRTC を使用するブラウザーである場合:
- このリポジトリの Python SDK ドキュメントの対象外として扱ってください。
- クライアントサイドフローとイベントモデルについては、公式の [Realtime API with WebRTC](https://developers.openai.com/api/docs/guides/realtime-webrtc/) [Realtime conversations](https://developers.openai.com/api/docs/guides/realtime-conversations/) ドキュメントを使用してください。
- ブラウザー WebRTC クライアントに加えてサイドバンドのサーバー接続が必要な場合は、公式の [Realtime server-side controls](https://developers.openai.com/api/docs/guides/realtime-server-controls/) ガイドを使用してください。
- このリポジトリがブラウザーサイド `RTCPeerConnection` 抽象化や、すぐに使えるブラウザー WebRTC サンプルを提供することは期待しないでください。
- このリポジトリの Python SDK ドキュメントの範囲外として扱ってください。
- クライアント側のフローとイベントモデルについては、公式の [WebRTC による Realtime API](https://developers.openai.com/api/docs/guides/realtime-webrtc/) および [Realtime conversations](https://developers.openai.com/api/docs/guides/realtime-conversations/) ドキュメントを使用してください。
- ブラウザー WebRTC クライアントの上にサイドバンドのサーバー接続が必要な場合は、公式の [Realtime server-side controls](https://developers.openai.com/api/docs/guides/realtime-server-controls/) ガイドを使用してください。
- このリポジトリがブラウザー側の `RTCPeerConnection` 抽象化や、すぐに使えるブラウザー WebRTC サンプルを提供することは期待しないでください。
このリポジトリには現在、ブラウザー WebRTC と Python サイドバンドを組み合わせた例も含まれていません。
このリポジトリには現在、ブラウザー WebRTC と Python サイドバンドを組み合わせた例も含まれていません。
## カスタムエンドポイントとアタッチポイント
[`RealtimeModelConfig`][agents.realtime.model.RealtimeModelConfig] のトランスポート設定インターフェースにより、デフォルトパスを調整できます。
[`RealtimeModelConfig`][agents.realtime.model.RealtimeModelConfig] のトランスポート設定サーフェスを使用すると、デフォルトパスを調整できます。
- `url`: WebSocket エンドポイントを上書きします
- `headers`: Azure 認証ヘッダーなどの明示的なヘッダーを提供します
- `headers`: Azure 認証ヘッダーなどの明示的なヘッダーを指定します
- `api_key`: API キーを直接、またはコールバック経由で渡します
- `call_id`: 既存の realtime 通話にアタッチします。このリポジトリで文書化されている例は SIP です。
- `playback_tracker`: 割り込み処理のために実際の再生進を報告します
- `call_id`: 既存の realtime 通話にアタッチします。このリポジトリで記載されている例は SIP です。
- `playback_tracker`: 割り込み処理のために実際の再生進を報告します
トポロジーを選択した後の詳細なライフサイクルと機能インターフェスについては、[Realtime agents guide](guide.md) を参照してください。
トポロジーを選択した後の詳細なライフサイクルと機能ーフェスについては、[Realtime エージェントガイド](guide.md) を参照してください。
+125 -40
View File
@@ -2,100 +2,185 @@
search:
exclude: true
---
# リリースプロセス / 変更履歴
# リリースプロセス変更履歴
このプロジェクトは、`0.Y.Z` 形式を使用する、semantic versioning のやや変更された版に従います。先頭の `0` は、この SDK が依然として急速に進化していることを示します。各コンポーネントのインクリメントは以下のとおりです。
このプロジェクトは、`0.Y.Z` 形式を使用した、セマンティックバージョニングをわずかに変更した方式に従います。先頭の `0` は、SDK が依然として急速に進化していることを示します。各構成要素は次のように更新します。
## マイナー (`Y`) バージョン
## マイナー`Y`バージョン
beta としてマークされていない公開インターフェースに対する **破壊的変更** がある場合、マイナーバージョン `Y`上げます。たとえば、`0.0.x` から `0.1.x` への変更には破壊的変更が含まれる可能性があります。
ベータと明記されていない公開インターフェースに **破壊的変更** がある場合、マイナーバージョン `Y`増やします。たとえば、`0.0.x` から `0.1.x` への移行には破壊的変更が含まれる可能性があります。
破壊的変更を望まない場合は、プロジェクトで `0.0.x` バージョンに固定することを推奨します。
破壊的変更を避けたい場合は、プロジェクトでバージョンを `0.0.x` に固定することを推奨します。
## パッチ (`Z`) バージョン
## パッチ`Z`バージョン
破壊的変更については `Z`上げます。
破壊的でない変更の場合は、`Z`増やします。
- バグ修正
- 新機能
- プライベートインターフェースの変更
- beta 機能の更新
- 非公開インターフェースの変更
- ベータ機能の更新
## 破壊的変更の変更履歴
## 破壊的変更履歴
### 0.18.0
このマイナーリリースには、破壊的変更は **ありません**。マイナーバージョンの更新は、Realtime エージェントのデフォルトモデル更新のみを目的としています。
主な変更点:
- Realtime エージェントのデフォルトモデルが `gpt-realtime-2.1` になり、新しい Realtime セットアップでは追加の設定なしで最新の推奨モデルが使用されるようになりました。
### 0.17.0
このバージョンでは、サンドボックスでローカルソースを実体化する際、ソースパスが `Manifest.extra_path_grants` の対象でない限り、`LocalFile.src``LocalDir.src` は実体化先の `base_dir` 内に保持されます。`base_dir` は、マニフェストの適用時点における SDK プロセスの現在の作業ディレクトリです。相対パスのローカルソースはそのディレクトリを基準に解決され、絶対パスのローカルソースは、すでにそのディレクトリ内にあるか、明示的な許可の対象である必要があります。これにより、ローカルアーティファクトの境界に関する問題が解消されますが、そのベースディレクトリ外にある信頼済みのホストファイルやディレクトリを意図的にサンドボックスワークスペースへコピーするアプリケーションには影響する可能性があります。
移行するには、`SandboxPathGrant` を使用してマニフェストレベルで信頼済みのホストルートを許可してください。サンドボックスがそれらのファイルを読み取るだけでよい場合は、読み取り専用にすることを推奨します。
```python
from pathlib import Path
from agents.sandbox import Manifest, SandboxPathGrant
from agents.sandbox.entries import Dir, LocalDir
# This is an absolute host path outside the SDK process base_dir.
TRUSTED_DOCS_ROOT = Path("/opt/my-app/docs")
manifest = Manifest(
extra_path_grants=(
# This host root is outside the SDK process base_dir, so the manifest must grant it.
SandboxPathGrant(path=str(TRUSTED_DOCS_ROOT), read_only=True),
),
entries={
# No grant is needed for local sources that stay under the SDK process base_dir.
"fixtures": LocalDir(src=Path("fixtures"), description="Local test fixtures."),
# This entry reads from the granted host root and copies it into the sandbox workspace.
"docs": LocalDir(src=TRUSTED_DOCS_ROOT, description="Trusted local documents."),
# Dir creates a sandbox workspace directory; it does not read from the host filesystem.
"output": Dir(description="Generated artifacts."),
},
)
```
`extra_path_grants` は、信頼済みのアプリケーション設定として扱ってください。アプリケーションが対象のホストパスを事前に承認していない限り、モデル出力やその他の信頼できないマニフェスト入力から許可設定を追加しないでください。
### 0.16.0
このバージョンでは、SDK のデフォルトモデルが `gpt-4.1` から `gpt-5.4-mini` に変更されました。これは、モデルを明示的に設定していないエージェントと実行に影響します。新しいデフォルトは GPT-5 モデルであるため、暗黙的なデフォルトモデル設定には、`reasoning.effort="none"``verbosity="low"` などの GPT-5 のデフォルト設定が含まれるようになりました。
以前のデフォルトモデルの動作を維持する必要がある場合は、エージェントまたは実行設定でモデルを明示的に指定するか、`OPENAI_DEFAULT_MODEL` 環境変数を設定してください。
```python
agent = Agent(name="Assistant", model="gpt-4.1")
```
主な変更点:
- `Runner.run``Runner.run_sync``Runner.run_streamed``max_turns=None` を指定し、ターン数の上限を無効にできるようになりました。
- サンドボックスワークスペースのハイドレーションでは、ローカル、Docker、プロバイダー支援型のすべてのサンドボックス実装において、絶対パスのシンボリックリンク先を含め、アーカイブルート外を指すシンボリックリンクを含む tar アーカイブが拒否されるようになりました。
### 0.15.0
このバージョンでは、モデルによる拒否が空のテキスト出力として扱われたり、structured outputs の場合に `MaxTurnsExceeded` になるまで実行ループが再試行されたりする代わりに、`ModelRefusalError` として明示的に公開されるようになりました。
これは、拒否のみを含むモデル応答が `final_output == ""` で完了することを想定していたコードに影響します。例外を送出せずに拒否を処理するには、`model_refusal` 実行エラーハンドラーを指定してください。
```python
result = Runner.run_sync(
agent,
input,
error_handlers={"model_refusal": lambda data: data.error.refusal},
)
```
structured outputs を使用するエージェントでは、ハンドラーからエージェントの出力スキーマに一致する値を返すことができ、SDK は他の実行エラーハンドラーの最終出力と同様にその値を検証します。
### 0.14.0
このマイナーリリースには、破壊的変更は **ありません**。ただし、主要な新しいベータ機能領域である Sandbox エージェントと、ローカル環境、コンテナ環境、ホスト環境で使用するために必要なランタイム、バックエンド、ドキュメントのサポートが追加されています。
主な変更点:
- `SandboxAgent``Manifest``SandboxRunConfig` を中心とする新しいベータ版サンドボックスランタイムインターフェースを追加しました。これにより、エージェントは、ファイル、ディレクトリ、Git リポジトリ、マウント、スナップショット、再開機能を備えた永続的で隔離されたワークスペース内で作業できます。
- `UnixLocalSandboxClient``DockerSandboxClient` により、ローカル開発およびコンテナ開発向けのサンドボックス実行バックエンドを追加しました。また、オプションの追加パッケージを通じて、Blaxel、Cloudflare、Daytona、E2B、Modal、Runloop、Vercel のホスト型プロバイダー統合も追加しました。
- サンドボックスのメモリサポートを追加し、以降の実行で以前の実行から得た知見を再利用できるようになりました。段階的な情報開示、複数ターンのグループ化、設定可能な分離境界、および S3 支援型ワークフローを含む永続化メモリのコード例が用意されています。
- ローカルおよび合成ワークスペースエントリ、S3/R2/GCS/Azure Blob Storage/S3 Files のリモートストレージマウント、移植可能なスナップショット、`RunState``SandboxSessionState`、または保存済みスナップショットを使用した再開フローを含む、より包括的なワークスペースおよび再開モデルを追加しました。
- `examples/sandbox/` 以下に、サンドボックスに関する多数のコード例とチュートリアルを追加しました。スキルを使用したコーディングタスク、ハンドオフ、メモリ、プロバイダー固有のセットアップに加え、コードレビュー、データルーム QA、Web サイトのクローン作成などのエンドツーエンドのワークフローを扱っています。
- サンドボックス対応のセッション準備、機能のバインド、状態のシリアライズ、統合トレーシング、プロンプトキャッシュキーのデフォルト設定、機密性の高い MCP 出力をより安全に秘匿する機能により、コアランタイムとトレーシングスタックを拡張しました。
### 0.13.0
このマイナーリリースでは **破壊的変更** は導入されませんが、注目すべき Realtime のデフォルト更新、新しい MCP 機能、ランタイム安定性の修正が含まれます。
このマイナーリリースには、破壊的変更**ありません**。ただし、注目すべき Realtime のデフォルト更新、新しい MCP 機能、ランタイム安定性向上が含まれています。
ハイライト:
主な変更点:
- デフォルトの websocket Realtime モデル `gpt-realtime-1.5` になり、新しい Realtime エージェントのセットアップでは追加設定なしで新しいモデル使用します
- `MCPServer` `list_resources()``list_resource_templates()``read_resource()` 公開`MCPServerStreamableHttp` `session_id` 公開るようになったため、streamable HTTP セッションを再接続やステートレスワーカー間で再開できます
- Chat Completions 統合`should_replay_reasoning_content` による reasoning-content の再生を選択できるようになり、LiteLLM / DeepSeek などのアダプタープロバイダー固有の reasoning / tool-call 継続性が向上しました
- `SQLAlchemySession` の同時初回書き込み、reasoning 削除後に assistant message ID が孤立した compaction リクエスト、`remove_all_tools()` が MCP / reasoning 項目を残してしまう問題、関数ツールのバッチエグゼキューターでの競合など、複数のランタイムおよびセッションの境界ケースを修正しました。
- デフォルトの WebSocket Realtime モデル `gpt-realtime-1.5` になり、新しい Realtime エージェントのセットアップでは追加設定なしで新しいモデル使用されるようになりました
- `MCPServer` `list_resources()``list_resource_templates()``read_resource()` 公開されるようになりました。また`MCPServerStreamableHttp` `session_id` 公開されるようになり、再接続やステートレスワーカー間でストリーミング可能な HTTP セッションを再開できるようになりました
- Chat Completions 統合で、`should_replay_reasoning_content` を通じて推論コンテンツのリプレイをオプトインできるようになりました。これにより、LiteLLM/DeepSeek などのアダプターにおいて、プロバイダー固有の推論やツール呼び出しの継続性が向上しま
- `SQLAlchemySession` での最初の書き込みの競合、推論の除去後に孤立したアシスタントメッセージ ID を含む圧縮リクエスト、`remove_all_tools()` の実行後も MCP/推論項目が残る問題、関数ツールのバッチ実行機構における競合状態など、ランタイムセッションに関する複数のエッジケースを修正しました。
### 0.12.0
このマイナーリリースでは **破壊的変更** は導入されません。主要な機能追加については [リリースノート](https://github.com/openai/openai-agents-python/releases/tag/v0.12.0) を確認してください。
このマイナーリリースには、破壊的変更**ありません**。主要な機能追加については[リリースノート](https://github.com/openai/openai-agents-python/releases/tag/v0.12.0)を確認してください。
### 0.11.0
このマイナーリリースでは **破壊的変更** は導入されません。主要な機能追加については [リリースノート](https://github.com/openai/openai-agents-python/releases/tag/v0.11.0) を確認してください。
このマイナーリリースには、破壊的変更**ありません**。主要な機能追加については[リリースノート](https://github.com/openai/openai-agents-python/releases/tag/v0.11.0)を確認してください。
### 0.10.0
このマイナーリリースでは **破壊的変更** は導入されませんが、OpenAI Responses ユーザー向けに重要な新機能領域として、Responses API の websocket transport サポートが含まれます。
このマイナーリリースには、破壊的変更**ありません**。ただし、OpenAI Responses ユーザー向けに重要な新機能領域である、Responses API の WebSocket トランスポートサポートが含まれています。
ハイライト:
主な変更点:
- OpenAI Responses モデル向けwebsocket transport サポートを追加しました(オプトイン。デフォルト transport は引き続き HTTP)。
- 複数ターンの実行共有の websocket 対応プロバイダーと `RunConfig` を再利用するための `responses_websocket_session()` ヘルパー / `ResponsesWebSocketSession` を追加しました。
- ストリーミング、ツール、承認、フォローアップターンを扱う新しい websocket ストリーミング例(`examples/basic/stream_ws.py`)を追加しました。
- OpenAI Responses モデルに WebSocket トランスポートのサポートを追加しました(オプトイン方式であり、HTTP が引き続きデフォルトのトランスポートです)。
- 複数ターンの実行間で、共有の WebSocket 対応プロバイダーと `RunConfig` を再利用するための `responses_websocket_session()` ヘルパー`ResponsesWebSocketSession` を追加しました。
- ストリーミング、ツール、承認、フォローアップターンを扱う新しい WebSocket ストリーミングのコード例(`examples/basic/stream_ws.py`)を追加しました。
### 0.9.0
このバージョンでは、Python 3.9 サポート対象外になりました。このメジャーバージョンは 3 か月前に EOL に到達しています。新しいランタイムバージョンアップグレードしてください。
このバージョンでは、Python 3.9 サポートを終了しました。このメジャーバージョンは 3 か月前に EOL を迎えています。より新しいランタイムバージョンアップグレードしてください。
さらに、`Agent#as_tool()` メソッドが返す値の型ヒント`Tool` から `FunctionTool` へ狭められました。この変更は通常は破壊的な問題を引き起こしませんが、コードがより広い union 型に依存している場合は、調整が必要になる可能性があります。
さらに、`Agent#as_tool()` メソッドから返される値の型ヒント`Tool` から `FunctionTool` に絞り込まれました。通常、この変更によって破壊的な問題が生じることはありませんが、コードがより広範なユニオン型に依存している場合は、調整が必要になる可能性があります。
### 0.8.0
このバージョンでは、2 つのランタイム動作変更により移行作業が必要になる可能性があります。
このバージョンでは、ランタイム動作に関する次の 2 つの変更により移行作業が必要になる場合があります。
- Function tools でラップされた **同期** Python callable は、イベントループスレッド上で実行される代わりに `asyncio.to_thread(...)` を介してワーカースレッド上で実行されるようになりました。ツールロジックがスレッドローカル状態やスレッド親和性のあるリソースに依存る場合は、非同期ツール実装へ移行するか、ツールコード内でスレッド親和性を明示してください。
- ローカル MCP ツールの失敗処理設定可能になり、デフォルト動作では実行全体を失敗させる代わりにモデル可視のエラー出力を返せるようになりました。fail-fast セマンティクスに依存している場合は、`mcp_config={"failure_error_function": None}` を設定してください。サーバーレベルの `failure_error_function` 値はエージェントレベル設定より優先されるため、明示的なハンドラーを持つ各ローカル MCP サーバーで `failure_error_function=None` を設定してください。
- **同期** Python 呼び出し可能オブジェクトをラップする関数ツールは、イベントループスレッド上で実行される代わりに`asyncio.to_thread(...)` を介してワーカースレッド上で実行されるようになりました。ツールロジックがスレッドローカル状態やスレッドアフィニティを持つリソースに依存している場合は、非同期ツール実装へ移行するか、ツールコード内でスレッドアフィニティを明示してください。
- ローカル MCP ツールの失敗処理設定可能になり、デフォルト動作では実行全体を失敗させる代わりにモデルから参照可能なエラー出力を返す場合があります。即時失敗の動作に依存している場合は、`mcp_config={"failure_error_function": None}` を設定してください。サーバーレベルの `failure_error_function` 値はエージェントレベル設定を上書きするため、明示的なハンドラーを持つ各ローカル MCP サーバーで `failure_error_function=None` を設定してください。
### 0.7.0
このバージョンでは、既存アプリケーションに影響しうるいくつかの動作変更があります。
このバージョンでは、既存アプリケーションに影響する可能性がある動作変更がいくつかあります。
- ネストたハンドオフ履歴は **オプトイン** になりました(デフォルトで無効)。v0.6.x のデフォルトのネスト動作に依存していた場合は、`RunConfig(nest_handoff_history=True)` を明示的に設定してください。
- `gpt-5.1` / `gpt-5.2` のデフォルト `reasoning.effort` `"none"` に変更されました(SDK デフォルト設定されていた以前のデフォルト `"low"` から変更)。プロンプトや品質 / コストプロファイル`"low"` に依存してい場合は、`model_settings` で明示的に設定してください。
- ネストされたハンドオフ履歴は **オプトイン** になりました(デフォルトで無効です)。v0.6.x のデフォルトのネスト動作に依存していた場合は、`RunConfig(nest_handoff_history=True)` を明示的に設定してください。
- `gpt-5.1``gpt-5.2` のデフォルト `reasoning.effort` が、SDK デフォルト設定で指定されていた従来の `"low"` から `"none"` に変更されました。プロンプトまたは品質/コスト特性`"low"` に依存してい場合は、`model_settings` で明示的に設定してください。
### 0.6.0
このバージョンでは、デフォルトのハンドオフ履歴生のユーザー / assistant ターンを公開する代わりに、単一の assistant メッセージにまとめられるようになり、下流エージェントに簡潔で予測可能な要約提供ます
- 既存の単一メッセージのハンドオフトランスクリプトは、デフォルトで `<CONVERSATION HISTORY>` ブロックの前に "For context, here is the conversation so far between the user and the previous agent:" 始まるようになり、下流エージェント明確ラベル付けされた要約を得られます
このバージョンでは、デフォルトのハンドオフ履歴が、生のユーザー/アシスタントのターンを公開する代わりに、1 件のアシスタントメッセージにまとめられるようになりました。これにより、後続のエージェントに簡潔で予測可能な要約提供されます
- 既存の単一メッセージ形式のハンドオフ記録は、デフォルトで `<CONVERSATION HISTORY>` ブロックの前に "For context, here is the conversation so far between the user and the previous agent:" という文言から始まるようになり、後続のエージェント明確ラベル付きの要約が提供されます
### 0.5.0
このバージョンでは、目に見える破壊的変更はありませんが、新機能と内部の重要な更新がいくつか含まれます。
このバージョンでは、目に見える破壊的変更は導入されていませんが、新機能と内部の重要な更新がいくつか含まれています。
- `RealtimeRunner` [SIP protocol connections](https://platform.openai.com/docs/guides/realtime-sip) を処理するサポートを追加しました
- Python 3.14 互換性のため`Runner#run_sync` の内部ロジックを大幅に改訂しました
- `RealtimeRunner` [SIP プロトコル接続](https://platform.openai.com/docs/guides/realtime-sip)を処理するためのサポートを追加しました
- Python 3.14 との互換性のため`Runner#run_sync` の内部ロジックを大幅に改訂しました
### 0.4.0
このバージョンでは、[openai](https://pypi.org/project/openai/) パッケージの v1.x はサポート対象外になりました。この SDK と合わせて openai v2.x を使用してください。
このバージョンでは、[openai](https://pypi.org/project/openai/) パッケージの v1.x バージョンはサポートされなくなりました。この SDK とともに openai v2.x を使用してください。
### 0.3.0
このバージョンでは、Realtime API サポートが gpt-realtime モデルとその API インターフェース( GA バージョン)に移行しま
このバージョンでは、Realtime API サポートが gpt-realtime モデルとその API インターフェース(GA )に移行しました
### 0.2.0
このバージョンでは、これまで引数として `Agent` を受け取っていたいくつかの箇所が、代わりに `AgentBase` を受け取るようになりました。たとえば、MCP サーバー`list_tools()` 呼び出しす。これは純粋に型付け上の変更であり、引き続き `Agent` オブジェクトを受け取ります。更新するには、`Agent``AgentBase` に置き換えて型エラーを修正してください
このバージョンでは、以前は引数として `Agent` を受け取っていた箇所の一部が、代わりに `AgentBase` を受け取るようになりました。たとえば、MCP サーバーの `list_tools()` 呼び出しが該当します。これは純粋に型付け上の変更であり、引き続き `Agent` オブジェクトを受け取ります。更新するには、`Agent``AgentBase` に置き換えて型エラーを修正するだけです
### 0.1.0
このバージョンでは、[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] に 2 つの新しいパラメーター `run_context``agent` が追加されました。`MCPServer` を継承するクラスに、これらのパラメーターを追加する必要があります。
このバージョンでは、[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] に `run_context``agent` という 2 つの新しいパラメーターが追加されました。`MCPServer` を継承するすべてのクラスに、これらのパラメーターを追加する必要があります。
+3 -3
View File
@@ -4,7 +4,7 @@ search:
---
# REPL ユーティリティ
この SDK は、ターミナルでエージェントの挙動を素早く対話的にテストできる `run_demo_loop` を提供します。
SDK は、ターミナルでエージェントの動作を直接すばやく対話的にテストするための `run_demo_loop` を提供します。
```python
@@ -19,6 +19,6 @@ if __name__ == "__main__":
asyncio.run(main())
```
`run_demo_loop` はループでユーザー入力を促し、ターン間会話履歴を保持します。デフォルトでは、生成されモデル出力をストリーミングします。上記の例を実行すると、`run_demo_loop` は対話型チャットセッションを開始します。入力を継続的に求め、これまでの会話履歴全体を保持することで(エージェントが何について話したかを把握できます)、生成と同時にエージェントの応答リアルタイムで自動的にストリーミングします。
`run_demo_loop` はループでユーザー入力を求め、ターン間会話履歴を保持します。デフォルトでは、生成されモデル出力をストリーミングします。上記の例を実行すると、run_demo_loop は対話型チャットセッションを開始します。入力を継続的に求め、ターン間の会話履歴全体を記憶し(そのためエージェントはこれまでに話し合われた内容を把握できます)、エージェントの応答が生成されるとリアルタイムで自動的にストリーミングします。
このチャットセッションを終了するには、`quit` または `exit` と入力して Enter を押すか、`Ctrl-D` キーボードショートカットを使用します。
このチャットセッションを終了するには、単に `quit` または `exit` と入力して Enter キーを押すか、`Ctrl-D` キーボードショートカットを使用します。
+67 -67
View File
@@ -4,95 +4,95 @@ search:
---
# 実行結果
`Runner.run` メソッドを呼び出すと、次の 2 種類の結果タイプのいずれかを受け取ります。
`Runner.run` メソッドを呼び出すと、次の 2 つの実行結果型のいずれかを受け取ります。
- `Runner.run(...)` または `Runner.run_sync(...)` からの [`RunResult`][agents.result.RunResult]
- `Runner.run_streamed(...)` からの [`RunResultStreaming`][agents.result.RunResultStreaming]
どちらも [`RunResultBase`][agents.result.RunResultBase] を継承しており、`final_output``new_items``last_agent``raw_responses``to_state()` などの共通の結果サーフェスを公開します。
どちらも [`RunResultBase`][agents.result.RunResultBase] を継承しており、`final_output``new_items``last_agent``raw_responses``to_state()` などの共通の実行結果サーフェスを公開します。
`RunResultStreaming` は、[`stream_events()`][agents.result.RunResultStreaming.stream_events]、[`current_agent`][agents.result.RunResultStreaming.current_agent]、[`is_complete`][agents.result.RunResultStreaming.is_complete]、[`cancel(...)`][agents.result.RunResultStreaming.cancel] などストリーミング固有の制御が追加されています。
`RunResultStreaming` は、[`stream_events()`][agents.result.RunResultStreaming.stream_events]、[`current_agent`][agents.result.RunResultStreaming.current_agent]、[`is_complete`][agents.result.RunResultStreaming.is_complete]、[`cancel(...)`][agents.result.RunResultStreaming.cancel] などストリーミング固有の制御機能を追加します。
## 適切な結果サーフェスの選択
## 適切な実行結果サーフェスの選択
ほとんどのアプリケーションで必要なのは、いくつかの結果プロパティまたはヘルパーだけです。
ほとんどのアプリケーションでは、いくつかの実行結果プロパティまたはヘルパーだけで十分です。
| 必要なもの | 使用 |
| 必要なもの... | 使用するもの |
| --- | --- |
| ユーザーに表示する最終回答 | `final_output` |
| ローカルの完全なトランスクリプトを含む、再生可能な次ターン入力リスト | `to_input_list()` |
| エージェント、ツール、ハンドオフ、承認メタデータを含むリッチな実行アイテム | `new_items` |
| 完全なローカルトランスクリプトを含む、リプレイ可能な次ターン入力リスト | `to_input_list()` |
| エージェント、ツール、ハンドオフ、承認メタデータを含む詳細な実行項目 | `new_items` |
| 通常、次のユーザーターンを処理すべきエージェント | `last_agent` |
| `previous_response_id` を用いた OpenAI Responses API チェーン | `last_response_id` |
| 保留中の承認と再開可能なスナップショット | `interruptions` `to_state()` |
| `previous_response_id` による OpenAI Responses API チェーン | `last_response_id` |
| 保留中の承認と再開可能なスナップショット | `interruptions` and `to_state()` |
| 現在のネストされた `Agent.as_tool()` 呼び出しに関するメタデータ | `agent_tool_invocation` |
| 生のモデル呼び出しまたはガードレール診断 | `raw_responses` とガードレール結果配列 |
| raw モデル呼び出しまたはガードレール診断 | `raw_responses` and the guardrail result arrays |
## 最終出力
[`final_output`][agents.result.RunResultBase.final_output] プロパティには、最後に実行されたエージェントの最終出力が含まれます。これは次のいずれかです。
- 最後のエージェントに `output_type` が定義されていな場合は `str`
- 最後のエージェントに出力型が定義されてい場合は `last_agent.output_type` 型のオブジェクト
- 承認による割り込みで一時停止した場合など、最終出力が生成される前に実行が停止した場合は `None`
- 最後のエージェントに `output_type` が定義されていなかった場合は `str`
- 最後のエージェントに出力型が定義されてい場合は `last_agent.output_type` 型のオブジェクト
- 承認中断で一時停止した場合など、最終出力が生成される前に実行が停止した場合は `None`
!!! note
`final_output``Any` 型です。ハンドオフにより実行を了するエージェントが変わる可能性があるため、SDK は取り得る出力型の完全な集合を静的に把握できません。
`final_output``Any` として型付けされています。ハンドオフによって、どのエージェントが実行を了するが変わる可能性があるため、SDK は考えられる出力型の全体集合を静的に把握できません。
ストリーミングモードでは、ストリームの処理が完了するまで `final_output``None` のままです。イベントごとの流れは [Streaming](streaming.md) を参照してください。
ストリーミングモードでは、ストリームの処理が完了するまで `final_output``None` のままです。イベントごとのフローについては、[ストリーミング](streaming.md)を参照してください。
## 入力、次ターン履歴、new items
## 入力、次ターン履歴、新規項目
これらのサーフェスは、それぞれ異なる問いに答えます。
これらのサーフェスは、それぞれ異なる問いに対応します。
| プロパティまたはヘルパー | 含まれる内容 | 最適な用途 |
| --- | --- | --- |
| [`input`][agents.result.RunResultBase.input] | この実行セグメントのベース入力。ハンドオフ入力フィルターが履歴を書き換えた場合、実行が継続たフィルター後の入力が反映されます。 | この実行が実際に入力として何を使ったかの監査 |
| [`to_input_list()`][agents.result.RunResultBase.to_input_list] | 実行入力アイテムビュー。既定`mode="preserve_all"` `new_items` から変換された完全な履歴を保持し`mode="normalized"` はハンドオフフィルタリングモデル履歴が書き換えられた際に正規の継続入力を優先します。 | 手動チャットループ、クライアント管理の会話状態、プレーンアイテム履歴の確認 |
| [`new_items`][agents.result.RunResultBase.new_items] | エージェント、ツール、ハンドオフ、承認メタデータを持つリッチな [`RunItem`][agents.items.RunItem] ラッパー。 | ログ、UI、監査、デバッグ |
| [`raw_responses`][agents.result.RunResultBase.raw_responses] | 実行内の各モデル呼び出しから得られる生の [`ModelResponse`][agents.items.ModelResponse] オブジェクト。 | プロバイダーレベルの診断や生レスポンスの確認 |
| [`input`][agents.result.RunResultBase.input] | この実行セグメントの基本入力です。ハンドオフ入力フィルターが履歴を書き換えた場合、実行が継続されたフィルター済み入力がここに反映されます。 | この実行が実際に入力として使用した内容の監査 |
| [`to_input_list()`][agents.result.RunResultBase.to_input_list] | 実行入力項目として見たビューです。デフォルト`mode="preserve_all"``new_items` から変換された完全な履歴を保持します。`mode="normalized"`ハンドオフフィルタリングによってモデル履歴が書き換えられた場合に、正規の継続入力を優先します。 | 手動チャットループ、クライアント管理の会話状態、プレーンな項目履歴の確認 |
| [`new_items`][agents.result.RunResultBase.new_items] | エージェント、ツール、ハンドオフ、承認メタデータを含む詳細な [`RunItem`][agents.items.RunItem] ラッパーです。 | ログ、UI、監査、デバッグ |
| [`raw_responses`][agents.result.RunResultBase.raw_responses] | 実行内の各モデル呼び出しからの raw [`ModelResponse`][agents.items.ModelResponse] オブジェクトです。 | プロバイダーレベルの診断または raw レスポンスの確認 |
運用では次のとおりです。
際には、次のように使い分けます。
- 実行のプレーンな入力アイテムビューが必要な場合は `to_input_list()` を使ます。
- ハンドオフフィルタリングネストされたハンドオフ履歴書き換え後、次の `Runner.run(..., input=...)` 呼び出し向けの正規ローカル入力が必要な場合は `to_input_list(mode="normalized")` を使ます。
- SDK に履歴の読み書きを任せたい場合は [`session=...`](sessions/index.md) を使ます。
- `conversation_id` `previous_response_id` による OpenAI のサーバー管理状態を使ている場合、通常は `to_input_list()` を再送せず、新しいユーザー入力のみを渡して保存済み ID を再利用します。
- ログ、UI、監査のために完全な変換済み履歴が必要な場合は、既定`to_input_list()` モードまたは `new_items` を使ます。
- 実行のプレーンな入力項目ビューが必要な場合は`to_input_list()` を使用します。
- ハンドオフフィルタリングまたはネストされたハンドオフ履歴書き換え後、次の `Runner.run(..., input=...)` 呼び出しに渡す正規ローカル入力が必要な場合は`to_input_list(mode="normalized")` を使用します。
- SDK に履歴の読み込みと保存を任せたい場合は[`session=...`](sessions/index.md) を使用します。
- `conversation_id` または `previous_response_id` を使って OpenAI のサーバー管理状態を使用している場合、通常は `to_input_list()` を再送信する代わりに、新しいユーザー入力のみを渡して保存済み ID を再利用します。
- ログ、UI、監査向けに完全な変換済み履歴が必要な場合は、デフォルト`to_input_list()` モードまたは `new_items` を使用します。
JavaScript SDK と異なり、Python はモデル形の差分のみを表す独立した `output` プロパティ公開ません。SDK メタデータが必要な `new_items` を使い、生のモデルペイロードが必要な `raw_responses` を確認してください。
JavaScript SDK と異なり、Python はモデル形の差分のみを表す個別の `output` プロパティ公開されません。SDK メタデータが必要な場合は `new_items` を使用し、raw モデルペイロードが必要な場合は `raw_responses` を確認してください。
コンピュータツールのリプレイは、生の Responses ペイロード形状に従います。プレビューモデルの `computer_call` アイテムは単一の `action` を保持し、`gpt-5.4` のコンピュータ呼び出しはバッチ化された `actions[]` を保持できます。[`to_input_list()`][agents.result.RunResultBase.to_input_list] と [`RunState`][agents.run_state.RunState] は、モデルが生成した形状をそのまま保持するため、手動リプレイ、一時停止/再開フロー、保存済みトランスクリプトはプレビュー版と GA の両方のコンピュータツール呼び出しで継続して機能します。ローカル実行結果は引き続き `new_items` `computer_call_output` アイテムとして現れます。
コンピュータツールのリプレイは、raw Responses ペイロード形状に従います。プレビューモデルの `computer_call` 項目は単一の `action` を保持しますが`gpt-5.5` のコンピュータ呼び出しはバッチ化された `actions[]` を保持できます。[`to_input_list()`][agents.result.RunResultBase.to_input_list] と [`RunState`][agents.run_state.RunState] は、モデルが生成した形状をそのまま保持するため、手動リプレイ、一時停止/再開フロー、保存済みトランスクリプトはプレビュー版と GA の両方のコンピュータツール呼び出しで引き続き機能します。ローカル実行結果は引き続き `new_items` `computer_call_output` 項目として表示されます。
### New items
### 新規項目
[`new_items`][agents.result.RunResultBase.new_items] は、実行中に何が起きたかを最もリッチに把握できるビューです。一般的なアイテムタイプは次のとおりです。
[`new_items`][agents.result.RunResultBase.new_items] は、実行中に何が起きたかを最も詳細に確認できるビューです。一般的な項目型は次のとおりです。
- アシスタントメッセージ用の [`MessageOutputItem`][agents.items.MessageOutputItem]
- 推論アイテム用の [`ReasoningItem`][agents.items.ReasoningItem]
- Responses ツール検索リクエストおよび読み込まれたツール検索結果用の [`ToolSearchCallItem`][agents.items.ToolSearchCallItem] [`ToolSearchOutputItem`][agents.items.ToolSearchOutputItem]
- ツール呼び出しとその結果用の [`ToolCallItem`][agents.items.ToolCallItem] [`ToolCallOutputItem`][agents.items.ToolCallOutputItem]
- 推論項目用の [`ReasoningItem`][agents.items.ReasoningItem]
- Responses ツール検索リクエストと、ロードされたツール検索の実行結果用の [`ToolSearchCallItem`][agents.items.ToolSearchCallItem] および [`ToolSearchOutputItem`][agents.items.ToolSearchOutputItem]
- ツール呼び出しとその実行結果用の [`ToolCallItem`][agents.items.ToolCallItem] および [`ToolCallOutputItem`][agents.items.ToolCallOutputItem]
- 承認待ちで一時停止したツール呼び出し用の [`ToolApprovalItem`][agents.items.ToolApprovalItem]
- ハンドオフ要求と完了した転送用の [`HandoffCallItem`][agents.items.HandoffCallItem] [`HandoffOutputItem`][agents.items.HandoffOutputItem]
- ハンドオフリクエストと完了済みの引き継ぎ用の [`HandoffCallItem`][agents.items.HandoffCallItem] および [`HandoffOutputItem`][agents.items.HandoffOutputItem]
エージェントの関連付け、ツール出力、ハンドオフ境界、承認境界が必要な場合は、`to_input_list()` より `new_items` を選んでください。
エージェントの関連付け、ツール出力、ハンドオフ境界、承認境界が必要な場合は、常に `to_input_list()` より `new_items` を選択してください。
ホストされたツール検索を使場合、モデルが出力した検索リクエストは `ToolSearchCallItem.raw_item`、当該ターンでどの名前空間関数・ホストされた MCP サーバーが読み込まれたか`ToolSearchOutputItem.raw_item` を確認してください。
ホストツール検索を使用する場合、モデルが生成した検索リクエストを確認するに`ToolSearchCallItem.raw_item`確認し、そのターンでどの名前空間関数、またはホスト型 MCP サーバーがロードされたかを確認するに`ToolSearchOutputItem.raw_item` を確認してください。
## 会話の継続または再開
### 次ターンのエージェント
[`last_agent`][agents.result.RunResultBase.last_agent] には、最後に実行されたエージェントが含まれます。これはハンドオフ後の次のユーザーターンで再利用するエージェントとして最適なことがよくあります。
[`last_agent`][agents.result.RunResultBase.last_agent] には、最後に実行されたエージェントが含まれます。これは多くの場合、ハンドオフ後の次のユーザーターンで再利用するのに最適なエージェントす。
ストリーミングモードでは、[`RunResultStreaming.current_agent`][agents.result.RunResultStreaming.current_agent] 実行進行に応じて更新されるため、ストリーム完了前にハンドオフを観察できます。
ストリーミングモードでは、[`RunResultStreaming.current_agent`][agents.result.RunResultStreaming.current_agent] 実行進行に合わせて更新されるため、ストリームが終了する前にハンドオフを観察できます。
### 割り込みと実行状態
### 中断と実行状態
ツールに承認が必要な場合、保留中の承認は [`RunResult.interruptions`][agents.result.RunResult.interruptions] または [`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] で公開されます。これには、直接ツールで発生した承認、ハンドオフ後に到達したツールで発生した承認、ネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行発生した承認が含まれる場合があります。
ツールに承認が必要な場合、保留中の承認は [`RunResult.interruptions`][agents.result.RunResult.interruptions] または [`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] で公開されます。これには、直接呼び出されたツール、ハンドオフ後に到達したツール、またはネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行によって発生した承認が含まれることがあります。
[`to_state()`][agents.result.RunResult.to_state] を呼び出して再開可能な [`RunState`][agents.run_state.RunState] を取得し、保留中アイテムを承認または拒否してから、`Runner.run(...)` または `Runner.run_streamed(...)` で再開します。
[`to_state()`][agents.result.RunResult.to_state] を呼び出して再開可能な [`RunState`][agents.run_state.RunState] を取得し、保留中の項目を承認または拒否してから、`Runner.run(...)` または `Runner.run_streamed(...)` で再開します。
```python
from agents import Agent, Runner
@@ -107,17 +107,17 @@ if result.interruptions:
result = await Runner.run(agent, state)
```
ストリーミング実行では、まず [`stream_events()`][agents.result.RunResultStreaming.stream_events] の消費を完了し、その後 `result.interruptions` を確認し`result.to_state()` から再開してください。承認フロー全体は [Human-in-the-loop](human_in_the_loop.md) を参照してください。
ストリーミング実行では、まず [`stream_events()`][agents.result.RunResultStreaming.stream_events] の消費を完了してから `result.interruptions` を確認し`result.to_state()` から再開してください。承認フロー全体については、[ヒューマンインザループ](human_in_the_loop.md)を参照してください。
### サーバー管理の継続
[`last_response_id`][agents.result.RunResultBase.last_response_id] は、この実行における最新のモデルレスポンス ID です。OpenAI Responses API チェーンを継続したい場合は、次ターンでこれを `previous_response_id` として渡します
[`last_response_id`][agents.result.RunResultBase.last_response_id] は、実行から得られた最新のモデルレスポンス ID です。OpenAI Responses API チェーンを継続したい場合は、次ターンで `previous_response_id` として渡してください
すでに `to_input_list()``session`、または `conversation_id` で会話を継続している場合、通常は `last_response_id` は不要です。マルチステップ実行すべてのモデルレスポンスが必要な場合は、代わりに `raw_responses` を確認してください。
すでに `to_input_list()``session`、または `conversation_id` で会話を継続している場合、通常は `last_response_id` は不要です。複数ステップ実行におけるすべてのモデルレスポンスが必要な場合は、代わりに `raw_responses` を確認してください。
## Agent-as-tool メタデータ
## ツールとしてのエージェントのメタデータ
結果がネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行から来ている場合、[`agent_tool_invocation`][agents.result.RunResultBase.agent_tool_invocation] は外側ツール呼び出しの不変メタデータを公開します。
実行結果がネストされた [`Agent.as_tool()`][agents.agent.Agent.as_tool] 実行に由来する場合、[`agent_tool_invocation`][agents.result.RunResultBase.agent_tool_invocation] は外側ツール呼び出しに関する変更不可のメタデータを公開します。
- `tool_name`
- `tool_call_id`
@@ -125,41 +125,41 @@ if result.interruptions:
通常のトップレベル実行では、`agent_tool_invocation``None` です。
これは特に `custom_output_extractor` 内で有用で、ネスト結果を後処理する際に外側のツール名、呼び出し ID、または生の引数が必要になることがあります。周辺の `Agent.as_tool()` パターンは [Tools](tools.md) を参照してください。
これは、ネストされた実行結果を後処理する際に外側のツール名、呼び出し ID、または生の引数が必要になることがあ`custom_output_extractor` 内で特に便利です。関連する `Agent.as_tool()` パターンについては、[ツール](tools.md)を参照してください。
そのネスト実行のパース済み structured outputs 入力も必要な場合は、`context_wrapper.tool_input` を読んでください。これは [`RunState`][agents.run_state.RunState] がネストツール入力向けに汎用的にシリアライズするフィールドであり`agent_tool_invocation` は現在のネスト呼び出し向けのライブ結果アクセサです。
そのネストされた実行のパース済み構造化入力も必要な場合は、`context_wrapper.tool_input` を読み取ってください。これは、ネストされたツール入力に対して [`RunState`][agents.run_state.RunState] が汎用的にシリアライズするフィールドです。一方`agent_tool_invocation`現在のネストされた呼び出しに対するライブの実行結果アクセサです。
## ストリーミングライフサイクルと診断
## ストリーミングライフサイクルと診断
[`RunResultStreaming`][agents.result.RunResultStreaming] は上記と同じ結果サーフェスを継承しますが、ストリーミング固有の制御を追加します。
[`RunResultStreaming`][agents.result.RunResultStreaming] は上記と同じ実行結果サーフェスを継承しますが、ストリーミング固有の制御機能を追加します。
- セマンティックなストリームイベントを消費する [`stream_events()`][agents.result.RunResultStreaming.stream_events]
- 実行途中アクティブエージェントを追跡する [`current_agent`][agents.result.RunResultStreaming.current_agent]
- ストリーミング実行が完全に終了したかを確認する [`is_complete`][agents.result.RunResultStreaming.is_complete]
- 実行を即時または現在ターン後に停止する [`cancel(...)`][agents.result.RunResultStreaming.cancel]
- セマンティックなストリームイベントを消費するための [`stream_events()`][agents.result.RunResultStreaming.stream_events]
- 実行途中アクティブエージェントを追跡するための [`current_agent`][agents.result.RunResultStreaming.current_agent]
- ストリーミング実行が完全に終了したかどうかを確認するための [`is_complete`][agents.result.RunResultStreaming.is_complete]
- 実行を即時または現在ターン後に停止するための [`cancel(...)`][agents.result.RunResultStreaming.cancel]
非同期イテレーターが終了するまで `stream_events()` を消費し続けてください。ストリーミング実行はそのイテレーターが終るまで完了しません。また、`final_output``interruptions``raw_responses`、セッション永続化の副作用などの要約プロパティは、最後に見えるトークン到着後も確定中である可能性があります。
非同期イテレーターが終了するまで `stream_events()` を消費し続けてください。そのイテレーターが終了するまで、ストリーミング実行は完了していません。また、`final_output``interruptions``raw_responses` などの要約プロパティや、セッション永続化の副作用は、目に見える最後のトークン到着した後もまだ確定中の場合があります。
`cancel()` を呼び出した場合、キャンセルとクリーンアップ正しく完了させるために `stream_events()` 消費続けてください。
`cancel()` を呼び出した場合、キャンセルとクリーンアップ正しく完了できるように、`stream_events()` 消費続けてください。
Python は、ストリーミング用の `completed` promise `error` プロパティを別途公開しません。終端ストリーミング失敗は `stream_events()` から例外送出として表面化し、`is_complete` は実行が終端状態に達したかどうかを反映します。
Python は、ストリーミング用の個別`completed` プロミス`error` プロパティは公開されません。終端的なストリーミング失敗は `stream_events()` から例外送出されることで表面化し、`is_complete` は実行が終端状態に達したかどうかを反映します。
### Raw responses
### raw レスポンス
[`raw_responses`][agents.result.RunResultBase.raw_responses] には、実行中に収集された生のモデルレスポンスが含まれます。マルチステップ実行では、たとえばハンドオフモデル/ツール/モデルの反復サイクルをまたいで、複数のレスポンスが生成されることがあります。
[`raw_responses`][agents.result.RunResultBase.raw_responses] には、実行中に収集された raw モデルレスポンスが含まれます。複数ステップ実行では、ハンドオフをまたいだり、モデル/ツール/モデルのサイクルが繰り返されたりする場合など、複数のレスポンスが生成されることがあります。
[`last_response_id`][agents.result.RunResultBase.last_response_id] は、`raw_responses` の最後のエントリの ID にすぎません。
### ガードレール結果
### ガードレールの実行結果
エージェントレベルのガードレールは [`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] として公開されます。
エージェントレベルのガードレールは[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] および [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] として公開されます。
ツールガードレールは、[`tool_input_guardrail_results`][agents.result.RunResultBase.tool_input_guardrail_results] [`tool_output_guardrail_results`][agents.result.RunResultBase.tool_output_guardrail_results] として別途公開されます。
ツールガードレールは、[`tool_input_guardrail_results`][agents.result.RunResultBase.tool_input_guardrail_results] および [`tool_output_guardrail_results`][agents.result.RunResultBase.tool_output_guardrail_results] として個別に公開されます。
これらの配列は実行全体で蓄積されるため、判定のログ、追加ガードレールメタデータの保存、実行がブロックされた理由のデバッグに有用です。
これらの配列は実行全体で蓄積されるため、判定のログ記録、追加ガードレールメタデータの保存、または実行がブロックされた理由のデバッグに役立ちます。
### コンテキストと使用量
[`context_wrapper`][agents.result.RunResultBase.context_wrapper] は、承認、使用量、ネストされた `tool_input` など SDK 管理ランタイムメタデータとともに、アプリコンテキストを公開します。
[`context_wrapper`][agents.result.RunResultBase.context_wrapper] は、アプリのコンテキストと、承認、使用量、ネストされた `tool_input` など SDK 管理するランタイムメタデータを公開します。
使用量は `context_wrapper.usage` で追跡されます。ストリーミング実行では、ストリーム最終チャンク処理が終わるまで使用量合計が遅延する場合があります。ラッパーの完全な形状と永続化時の注意点は [Context management](context.md) を参照してください。
使用量は `context_wrapper.usage` で追跡されます。ストリーミング実行では、ストリーム最終チャンク処理されるまで使用量合計が遅れて反映される場合があります。ラッパーの完全な形状と永続化に関する注意事項については、[コンテキスト管理](context.md)を参照してください。
+259 -140
View File
@@ -4,11 +4,11 @@ search:
---
# エージェントの実行
[`Runner`][agents.run.Runner] クラスをしてエージェントを実行できます。方法は 3 つあります。
[`Runner`][agents.run.Runner] クラスを使用してエージェントを実行できます。次の 3 つの方法があります。
1. [`Runner.run()`][agents.run.Runner.run]非同期で実行され、[`RunResult`][agents.result.RunResult] を返します。
2. [`Runner.run_sync()`][agents.run.Runner.run_sync]同期メソッドで、内部的には `.run()` を実行するだけです。
3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]非同期で実行され、[`RunResultStreaming`][agents.result.RunResultStreaming] を返します。ストリーミングモードで LLM を呼び出し、受信したイベントをそのままストリーミングします。
1. [`Runner.run()`][agents.run.Runner.run]非同期で実行、[`RunResult`][agents.result.RunResult] を返します。
2. [`Runner.run_sync()`][agents.run.Runner.run_sync]同期メソッドで、内部的には `.run()` を実行します。
3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]非同期で実行、[`RunResultStreaming`][agents.result.RunResultStreaming] を返します。ストリーミングモードで LLM を呼び出し、受信したイベントをそのままストリーミングします。
```python
from agents import Agent, Runner
@@ -23,46 +23,46 @@ async def main():
# Infinite loop's dance
```
詳細は [結果ガイド](results.md) を参照してください。
詳細については、[実行結果ガイド](results.md)を参照してください。
## Runner のライフサイクルと設定
### エージェントループ
`Runner` の run メソッドを使うときは、開始エージェントと入力を渡します。入力には次を指定できます。
`Runner` の run メソッドを使用する場合、開始エージェントと入力を渡します。入力には次のものを使用できます。
- 文字列 (ユーザーメッセージとして扱われます)
- OpenAI Responses API 形式の入力アイテムのリスト
- 中断された実行を再開する場合 [`RunState`][agents.run_state.RunState]
- 文字列ユーザーメッセージとして扱われます
- OpenAI Responses API 形式の入力項目のリスト
- 中断された実行を再開する場合 [`RunState`][agents.run_state.RunState]
その後、Runner は次のループを実行します。
その後、runner はループを実行します。
1. 現在の入力を使って、現在のエージェントに対して LLM を呼び出します。
1. 現在のエージェントに対して、現在の入力で LLM を呼び出します。
2. LLM が出力を生成します。
1. LLM が `final_output` を返した場合、ループ終了し結果を返します。
1. LLM が `final_output` を返した場合、ループ終了して実行結果を返します。
2. LLM がハンドオフを行った場合、現在のエージェントと入力を更新し、ループを再実行します。
3. LLM がツール呼び出しを生成した場合、それらを実行し結果を追記してループを再実行します。
3. 渡された `max_turns` を超えた場合、[`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 例外を送出します。
3. LLM がツール呼び出しを生成した場合、そのツール呼び出しを実行し結果を追加し、ループを再実行します。
3. 渡された `max_turns` を超えた場合、[`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 例外を発生させます。このターン制限を無効にするには、`max_turns=None` を渡します。
!!! note
LLM 出力「最終出力」とみなす条件は、期待された型のテキスト出力生成し、かつツール呼び出しがないことです。
LLM 出力「最終出力」と見なされる条件は、目的の型のテキスト出力生成され、ツール呼び出しが存在しないことです。
### ストリーミング
ストリーミングを使と、LLM 実行中ストリーミングイベントも受け取れます。ストリーム完了、[`RunResultStreaming`][agents.result.RunResultStreaming] には、生成されたすべての新しい出力を含む実行完全な情報が入ります。ストリーミングイベントは `.stream_events()` で取得できます。詳細は [ストリーミングガイド](streaming.md) を参照してください。
ストリーミングを使用すると、LLM 実行中ストリーミングイベントも受信できます。ストリーム完了すると、[`RunResultStreaming`][agents.result.RunResultStreaming] には、生成されたすべての新しい出力を含む実行に関する完全な情報が格納されます。ストリーミングイベント`.stream_events()` を呼び出せます。詳細については、[ストリーミングガイド](streaming.md)を参照してください。
#### Responses WebSocket トランスポート (任意ヘルパー)
#### Responses WebSocket トランスポート(オプションのヘルパー
OpenAI Responses websocket トランスポートを有効しても、通常の `Runner` API をそのまま使えます。接続再利用には websocket session helper の利用を推奨しますが、必須ではありません。
OpenAI Responses websocket トランスポートを有効しても、通常の `Runner` API を引き続き使用できます。接続再利用するには websocket セッションヘルパーの使用を推奨しますが、必須ではありません。
これは websocket トランスポート上の Responses API であり、[Realtime API](realtime/guide.md) ではありません。
これは websocket トランスポート上の Responses API であり、[Realtime API](realtime/guide.md)ではありません。
トランスポート選択ルールと、具体的な model オブジェクトや custom provider に関する注意点は、[Models](models/index.md#responses-websocket-transport) を参照してください。
トランスポート選択ルール、および具体的なモデルオブジェクトやカスタムプロバイダーに関する注意事項については、[モデル](models/index.md#responses-websocket-transport)を参照してください。
##### パターン 1: session helper なし (動作可)
##### パターン 1:セッションヘルパーなし(動作可能)
websocket トランスポートだけ使いたい場合、また SDK に共有 provider / session を管理させる必要がない場合に使ます。
websocket トランスポートのみが必要で、共有プロバイダーやセッションを SDK に管理させる必要がない場合に使用します。
```python
import asyncio
@@ -85,11 +85,11 @@ async def main():
asyncio.run(main())
```
このパターンは単発実行には問題ありません`Runner.run()` / `Runner.run_streamed()` を繰り返し呼場合、同じ `RunConfig` / provider インスタンスを手動で再利用しない限り、実行で再接続が発生する可能性があります。
このパターンは、単一の実行に適しています`Runner.run()` / `Runner.run_streamed()` を繰り返し呼び出す場合、同じ `RunConfig` / プロバイダーインスタンスを手動で再利用しない限り、実行ごとに再接続される可能性があります。
##### パターン 2: `responses_websocket_session()` 使用 (マルチターン再利用に推奨)
##### パターン 2`responses_websocket_session()` 使用(複数ターンでの再利用に推奨
複数実行で websocket 対応 provider `RunConfig`共有したい場合 (同じ `run_config` を継承するネストされた agent-as-tool 呼び出しを含む) は [`responses_websocket_session()`][agents.responses_websocket_session] を使ます。
複数実行で websocket 対応の共有プロバイダー`RunConfig`使用する場合は、[`responses_websocket_session()`][agents.responses_websocket_session] を使用します。これには、同じ `run_config` を継承する、ネストされた Agents-as-tools 呼び出しも含まれます。
```python
import asyncio
@@ -100,7 +100,9 @@ from agents import Agent, responses_websocket_session
async def main():
agent = Agent(name="Assistant", instructions="Be concise.")
async with responses_websocket_session() as ws:
async with responses_websocket_session(
responses_websocket_options={"ping_interval": 20.0, "ping_timeout": 60.0},
) as ws:
first = ws.run_streamed(agent, "Say hello in one short sentence.")
async for _event in first.stream_events():
pass
@@ -117,63 +119,114 @@ async def main():
asyncio.run(main())
```
ストリーミング結果の消費は context を抜ける前に完了してください。websocket リクエストが進行中のまま context を終了すると、共有接続が強制的に閉じられる可能性があります。
コンテキストを終了する前に、ストリーミングされた実行結果の処理を完了してください。websocket リクエストが進行中の状態でコンテキストを終了すると、共有接続が強制的に閉じられる可能性があります。
### RunConfig
長時間の推論ターンで websocket の keepalive タイムアウトが発生する場合は、`ping_timeout` を大きくするか、`ping_timeout=None` を設定してハートビートタイムアウトを無効にしてください。websocket のレイテンシよりも信頼性が重要な実行では、HTTP/SSE トランスポートを使用してください。
`run_config` パラメーターを使うと、エージェント実行のグローバル設定をいくつか構成できます。
### 実行設定
#### 共通の run_config カテゴリー
`run_config` パラメーターを使用すると、エージェントの実行に関するグローバル設定を構成できます。
`RunConfig` を使うと、各エージェント定義を変更せずに、単一実行の挙動を上書きできます。
#### 一般的な実行設定カテゴリー
##### model / provider / session の既定値
各エージェントの定義を変更せず、単一の実行に対する動作を上書きするには、`RunConfig` を使用します。
- [`model`][agents.run.RunConfig.model]: 各 Agent の `model` 設定に関係なく、グローバルで使う LLM model を設定できます。
- [`model_provider`][agents.run.RunConfig.model_provider]: model 名の解決に使う model provider で、既定は OpenAI です。
- [`model_settings`][agents.run.RunConfig.model_settings]: エージェント固有設定を上書きします。例えばグローバルな `temperature``top_p` を設定できます。
- [`session_settings`][agents.run.RunConfig.session_settings]: 実行中に履歴を取得する際の session レベル既定値 (例: `SessionSettings(limit=...)`) を上書きします。
- [`session_input_callback`][agents.run.RunConfig.session_input_callback]: Sessions 使用時に、各ターン前に新規ユーザー入力を session 履歴へどうマージするかをカスタマイズします。callback は同期 / 非同期のどちらでも可能です。
##### モデル、プロバイダー、セッションのデフォルト設定
##### ガードレール / ハンドオフ / model 入力整形
- [`model`][agents.run.RunConfig.model]:各 Agent に設定されている `model` に関係なく、使用するグローバルな LLM モデルを設定できます。
- [`model_provider`][agents.run.RunConfig.model_provider]:モデル名を検索するためのモデルプロバイダーです。デフォルトは OpenAI です。
- [`model_settings`][agents.run.RunConfig.model_settings]:エージェント固有の設定を上書きします。たとえば、グローバルな `temperature` または `top_p` を設定できます。
- [`session_settings`][agents.run.RunConfig.session_settings]:実行中に履歴を取得する際のセッションレベルのデフォルト設定(たとえば、`SessionSettings(limit=...)`)を上書きします。
- [`session_input_callback`][agents.run.RunConfig.session_input_callback]Sessions の使用時に、各ターンの前に新しいユーザー入力をセッション履歴とマージする方法をカスタマイズします。コールバックは同期または非同期にできます。
- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: すべての実行に含める入力 / 出力ガードレールのリストです。
- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]: ハンドオフ側に既存設定がない場合、すべてのハンドオフに適用されるグローバル入力フィルターです。新しいエージェントへ送る入力を編集できます。詳細は [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] のドキュメントを参照してください。
- [`nest_handoff_history`][agents.run.RunConfig.nest_handoff_history]: 次のエージェント呼び出し前に、直前までの transcript を 1 つの assistant message に折りたたむ opt-in beta です。ネストされたハンドオフの安定化中のため既定では無効です。有効化は `True`、raw transcript をそのまま渡す場合は `False` にします。[Runner methods][agents.run.Runner] は `RunConfig` 未指定時に自動作成するため、quickstart や examples では既定で無効のままです。また明示的な [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] callback は引き続き優先されます。個別ハンドオフでは [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history] で上書きできます。
- [`handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper]: `nest_handoff_history` を有効化した際に、正規化 transcript (履歴 + ハンドオフ項目) を受け取る任意 callable です。次エージェントへ渡す入力アイテムの正確なリストを返す必要があり、完全な handoff filter を書かずに組み込み要約を置き換えられます
- [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter]: model 呼び出し直前に、完全に準備された model 入力 (`instructions` と入力アイテム) を編集する hook です。例: 履歴のトリミングやシステムプロンプト注入
- [`reasoning_item_id_policy`][agents.run.RunConfig.reasoning_item_id_policy]: Runner が過去出力を次ターンの model 入力へ変換する際に、reasoning item ID を保持するか省略するかを制御します。
##### ガードレール、ハンドオフ、モデル入力の整形
- [`input_guardrails`][agents.run.RunConfig.input_guardrails]、[`output_guardrails`][agents.run.RunConfig.output_guardrails]:すべての実行に含める入力ガードレールまたは出力ガードレールのリストです。
- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]:ハンドオフにフィルターがまだ設定されていない場合、すべてのハンドオフに適用するグローバル入力フィルターです。入力フィルターを使用すると、新しいエージェントに送信される入力を編集できます。詳細については、[`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] のドキュメントを参照してください
- [`nest_handoff_history`][agents.run.RunConfig.nest_handoff_history]:次のエージェントを呼び出前に、それまでのトランスクリプトを単一の assistant メッセージにまとめる、オプトインのベータ機能です。ネストされたハンドオフの安定化を進めているため、デフォルトでは無効です。有効にするには `True` を設定し、raw トランスクリプトをそのまま渡すには `False` のままにします。[Runner の各メソッド][agents.run.Runner]は、`RunConfig` が渡されなかった場合に自動的に作成するため、クイックスタートとコード例ではデフォルトで無効のままです。また、明示的な [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] コールバックは引き続きこの設定を上書きします。個々のハンドオフでは、[`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history] を使用してこの設定を上書きできます
- [`handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper]`nest_handoff_history` を有効にした際に、正規化されたトランスクリプト(履歴とハンドオフ項目)を受け取るオプションの callable です。次のエージェントに転送する入力項目の正確なリストを返す必要があり、完全なハンドオフフィルターを記述することなく、組み込みの要約を置き換えられます。
- [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter]:モデル呼び出しの直前に、完全に準備されたモデル入力(instructions と入力項目)を編集するためのフックです。たとえば、履歴の短縮やシステムプロンプトの挿入に使用できます。
- [`reasoning_item_id_policy`][agents.run.RunConfig.reasoning_item_id_policy]runner が以前の出力を次のターンのモデル入力に変換するときに、推論項目 ID を保持するか省略するかを制御します。
##### トレーシングと可観測性
- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]: 実行全体の [トレーシング](tracing.md) を無効にできます。
- [`tracing`][agents.run.RunConfig.tracing]: この実行の exporter / processor / tracing metadata を上書きする [`TracingConfig`][agents.tracing.TracingConfig] を渡します。
- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: LLM やツール呼び出しの入出力など、機データをトレースに含めるかを設定します。
- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: この実行のトレーシング workflow 名、trace ID、trace group ID を設定します。少なくとも `workflow_name` 設定を推奨します。group ID は任意で、複数実行にまたがるトレース関連付けに使えます。
- [`trace_metadata`][agents.run.RunConfig.trace_metadata]: すべてのトレースに含める metadata です。
- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]実行全体の[トレーシング](tracing.md)を無効にできます。
- [`tracing`][agents.run.RunConfig.tracing]:実行ごとのトレーシング API キーなど、トレースのエクスポート設定を上書きするには、[`TracingConfig`][agents.tracing.TracingConfig] を渡します。
- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]LLM やツール呼び出しの入出力など、機密である可能性があるデータをトレースに含めるかどうかを設定します。
- [`workflow_name`][agents.run.RunConfig.workflow_name][`trace_id`][agents.run.RunConfig.trace_id][`group_id`][agents.run.RunConfig.group_id]実行のトレーシングワークフロー名、トレース ID、トレースグループ ID を設定します。少なくとも `workflow_name` 設定することを推奨します。グループ ID は、複数実行にわたってトレース関連付けるためのオプションフィールドです。
- [`trace_metadata`][agents.run.RunConfig.trace_metadata]すべてのトレースに含めるメタデータです。
##### ツール承認とツールエラー
##### ツールの実行、承認、エラー動
- [`tool_error_formatter`][agents.run.RunConfig.tool_error_formatter]: 承認フローでツール呼び出しが拒否された際に、model に見えるメッセージをカスタマイズします。
- [`tool_execution`][agents.run.RunConfig.tool_execution]:同時に実行する関数ツールの数を制限するなど、ローカルツール呼び出しに対する SDK 側の実行動作を設定します。
- [`tool_not_found_behavior`][agents.run.RunConfig.tool_not_found_behavior]:モデルが出力した、解決できない関数ツール呼び出しを runner が処理する方法を設定します。デフォルトでは `ModelBehaviorError` が発生します。代わりに、モデルから参照可能なエラー出力を返すようオプトインできます。
- [`tool_error_formatter`][agents.run.RunConfig.tool_error_formatter]:承認の拒否や、オプトインしたツール未検出時の出力など、モデルから参照可能なツールエラーメッセージをカスタマイズします。
ネストされたハンドオフは opt-in beta として利用できます。折りたたみ transcript の挙動は `RunConfig(nest_handoff_history=True)` を渡すか、特定のハンドオフ `handoff(..., nest_handoff_history=True)` を設定すると有効になります。raw transcript (既定) を維持したい場合は、フラグを設定のままにするか、必要どおりに会話をそのまま転送する `handoff_input_filter` (または `handoff_history_mapper`) を指定してください。custom mapper を書かずに生成要約のラッパーテキストを変更するには、[`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] を呼びます (既定値復元は [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers])
ネストされたハンドオフは、オプトインのベータ機能として利用できます。トランスクリプトをまとめる動作を有効にするには、`RunConfig(nest_handoff_history=True)` を渡すか、特定のハンドオフに対して `handoff(..., nest_handoff_history=True)` を設定します。raw トランスクリプトを保持する場合(デフォルト)は、フラグを設定しないか、必要に応じて会話をそのまま転送する `handoff_input_filter`または `handoff_history_mapper`を指定します。カスタム mapper を記述せずに生成される要約で使用されるラッパーテキストを変更するには、[`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] を呼び出します。デフォルトに戻すには [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers] を呼び出します
#### RunConfig 詳細
#### 実行設定の詳細
##### `tool_execution`
実行時のローカル関数ツールの同時実行数を制限するなど、ローカル関数ツールに対する SDK 側の動作を設定する場合は、`tool_execution` を使用します。
```python
from agents import Agent, RunConfig, Runner, ToolExecutionConfig
agent = Agent(name="Assistant", tools=[...])
result = await Runner.run(
agent,
"Run the required tool calls.",
run_config=RunConfig(
tool_execution=ToolExecutionConfig(
max_function_tool_concurrency=2,
pre_approval_tool_input_guardrails=True,
),
),
)
```
`max_function_tool_concurrency=None` はデフォルトの動作を維持します。モデルが 1 ターンで複数の関数ツール呼び出しを出力すると、SDK は出力されたすべてのローカル関数ツール呼び出しを開始します。同時に実行するローカル関数ツールの数を制限するには、整数値を設定します。
これは、プロバイダー側の [`ModelSettings.parallel_tool_calls`][agents.model_settings.ModelSettings.parallel_tool_calls] とは別のものです。`parallel_tool_calls` は、モデルが 1 回のレスポンスで複数のツール呼び出しを出力できるかどうかを制御します。`tool_execution.max_function_tool_concurrency` は、モデルがツール呼び出しを出力した後に、SDK がローカル関数ツール呼び出しを実行する方法を制御します。
`pre_approval_tool_input_guardrails=False` はデフォルトの承認フローを維持します。関数ツールに承認が必要な場合、実行は最初に一時停止し、ツール入力ガードレールは承認後の実行直前にのみ実行されます。保留中の承認による中断が発生する前に関数ツールの入力ガードレールを実行する場合は、`True` に設定します。この承認前チェックに合格した呼び出しでも、承認後に同じ入力ガードレールが再度実行されるため、時間依存のチェックは実行前に再検証されます。
##### `tool_not_found_behavior`
デフォルトでは、モデルが現在のエージェントで使用可能な関数ツールのいずれにも一致しない関数ツール呼び出しを出力すると、runner は `ModelBehaviorError` を発生させます。
実行を復旧可能な状態に保つ場合は、`tool_not_found_behavior="return_error_to_model"` を設定します。このモードでは、SDK は解決できないツール呼び出しに対する `function_call_output` を追加し、モデルを再実行します。これにより、モデルは使用可能なツールを選択するか、そのツールを使用せずに回答できます。
```python
from agents import Agent, RunConfig, Runner
agent = Agent(name="Assistant", tools=[...])
result = await Runner.run(
agent,
"Handle this request with the available tools.",
run_config=RunConfig(tool_not_found_behavior="return_error_to_model"),
)
```
現在、このオプションは解決できない関数ツール呼び出しにのみ適用されます。その他の無効なツールペイロードには、既存のエラー動作が引き続き適用されます。
##### `tool_error_formatter`
`tool_error_formatter` を使うと、承認フローでツール呼び出しが拒否されたときに model へ返すメッセージをカスタマイズできます。
SDK がモデルから参照可能なツールエラー出力を作成する際にモデルへ返すメッセージをカスタマイズするには、`tool_error_formatter` を使用します。
formatter は以下を含む [`ToolErrorFormatterArgs`][agents.run_config.ToolErrorFormatterArgs] を受け取ります。
formatter は、次の内容を含む [`ToolErrorFormatterArgs`][agents.run_config.ToolErrorFormatterArgs] を受け取ります。
- `kind`: エラーカテゴリー。現時点では `"approval_rejected"` です。
- `tool_type`: ツール runtime (`"function"``"computer"``"shell"``"apply_patch"`)
- `tool_name`: ツール名。
- `call_id`: ツール呼び出し ID。
- `default_message`: SDK 既定の model 向けメッセージ。
- `run_context`: アクティブな run context wrapper
- `kind``"approval_rejected"` `"tool_not_found"` などのエラーカテゴリーです。
- `tool_type`ツールのランタイム(`"function"``"computer"``"shell"``"apply_patch"`、または `"custom"`)です
- `tool_name`ツール名です
- `call_id`ツール呼び出し ID です
- `default_message`:モデルから参照可能な SDK のデフォルトメッセージです
- `run_context`アクティブな実行コンテキストのラッパーです
文字列を返すとメッセージを置換し、`None` を返すと SDK 既定値を使います。
メッセージを置き換えるには文字列を返し、SDK のデフォルトを使用するには `None` を返します。
```python
from agents import Agent, RunConfig, Runner, ToolErrorFormatterArgs
@@ -185,6 +238,8 @@ def format_rejection(args: ToolErrorFormatterArgs[None]) -> str | None:
f"Tool call '{args.tool_name}' was rejected by a human reviewer. "
"Ask for confirmation or propose a safer alternative."
)
if args.kind == "tool_not_found":
return f"Tool '{args.tool_name}' is not available. Choose one of the listed tools."
return None
@@ -198,56 +253,56 @@ result = Runner.run_sync(
##### `reasoning_item_id_policy`
`reasoning_item_id_policy` は、Runner が履歴を引き継ぐ際 (例: `RunResult.to_input_list()` や session-backed 実行) に、reasoning item を次ターン model 入力へどう変換するかを制御します
`reasoning_item_id_policy` は、runner が履歴を次のターンへ引き継ぐ際に、推論項目を次のターンのモデル入力へ変換する方法を制御します(たとえば、`RunResult.to_input_list()` またはセッションに基づく実行を使用する場合)
- `None` または `"preserve"` (既定): reasoning item ID を保持します。
- `"omit"`: 生成される次ターン入力から reasoning item ID を削除します。
- `None` または `"preserve"`(デフォルト):推論項目 ID を保持します。
- `"omit"`生成される次ターン入力から推論項目 ID を削除します。
`"omit"` は主に、reasoning item が `id` 付きで送信されたが必須の後続 item がない場合に発生する Responses API 400 エラー群への opt-in 緩和策として使います (例: `Item 'rs_...' of type 'reasoning' was provided without its required following item.`)
`"omit"` は主に、推論項目が `id` を伴って送信される一方で、必須の後続項目がない場合に発生する Responses API 400 エラー群に対する、オプトインの緩和策として使用します(例:`Item 'rs_...' of type 'reasoning' was provided without its required following item.`
これは、SDK が過去出力から follow-up 入力を構築するマルチターンエージェント実行時に発生し得ます (session 永続化、サーバー管理 conversation delta、streamed / non-streamed follow-up ターン、resume 経路を含む)。reasoning item ID が保持され、provider 側で対応する後続 item とのペア維持が要求される場合です。
これは、SDK が以前の出力から後続入力を構築し、推論項目 ID が保持される一方で、プロバイダーがその ID と対応する後続項目とのペアを維持するよう要求する場合に、複数ターンエージェント実行で発生する可能性があります。これには、セッションの永続化、サーバー管理の会話差分、ストリーミング/非ストリーミングの後続ターン、再開パスが含まれます。
`reasoning_item_id_policy="omit"` を設定すると reasoning 内容は維持しつつ reasoning item `id` を削除するため、SDK 生成 follow-up 入力での API 不変条件に抵触するを回避できます。
`reasoning_item_id_policy="omit"` を設定すると、推論内容を保持しながら推論項目の `id` を削除できます。これにより、SDK 生成する後続入力で、その API 不変条件に抵触することを回避できます。
適用範囲の注意:
適用範囲に関する注意事項:
- 影響するのは、SDK が follow-up 入力構築時に生成 / 転送する reasoning item のみです。
- ユーザー提供の初期入力アイテムは書き換えません。
- `call_model_input_filter` は、この policy 適用後に意図的に reasoning ID を再導入できます。
- これは、SDK が後続入力構築するときに生成または転送する推論項目のみを変更します。
- ユーザーが指定した初期入力項目は書き換えません。
- このポリシーの適用後でも、`call_model_input_filter` によって意図的に推論 ID を再導入できます。
## 状態と会話管理
## 状態と会話管理
### メモリ戦略の選択
状態を次ターンへ引き継ぐ一般的な方法は 4 つあります。
状態を次ターンへ引き継ぐ一般的な方法は 4 つあります。
| Strategy | Where state lives | Best for | What you pass on the next turn |
| 戦略 | 状態の保存場所 | 最適な用途 | 次のターンで渡すもの |
| --- | --- | --- | --- |
| `result.to_input_list()` | アプリメモリ | 小規模チャットループ、完全手動制御、任意 provider | `result.to_input_list()` のリスト + 次のユーザーメッセージ |
| `session` | 自身のストレージ + SDK | 永続チャット状態、再開可能実行、カスタムストア | 同じ `session` インスタンス、または同じ store を指す別インスタンス |
| `conversation_id` | OpenAI Conversations API | ワーカー / サービス間で共有したい名前付きサーバー側会話 | 同じ `conversation_id` + 新しいユーザーターンのみ |
| `previous_response_id` | OpenAI Responses API | conversation リソースを作らない軽量なサーバー管理継続 | `result.last_response_id` + 新しいユーザーターンのみ |
| `result.to_input_list()` | アプリメモリ | 小規模チャットループ、完全手動制御、任意のプロバイダー | `result.to_input_list()` のリスト次のユーザーメッセージ |
| `session` | ストレージ SDK | 永続的なチャット状態、再開可能実行、カスタムストア | 同じ `session` インスタンス、または同じストアを参照する別のインスタンス |
| `conversation_id` | OpenAI Conversations API | ワーカーサービス間で共有する、名前付きサーバー側会話 | 同じ `conversation_id` 新しいユーザーターンのみ |
| `previous_response_id` | OpenAI Responses API | 会話リソースを作成せずに行う軽量なサーバー管理継続 | `result.last_response_id` 新しいユーザーターンのみ |
`result.to_input_list()``session` はクライアント管理です。`conversation_id``previous_response_id` は OpenAI 管理で、OpenAI Responses API 使用のみ適用されます。多くのアプリでは、1 つの会話につき 1 つの永続化戦略を選ぶのが適切です。クライアント管理履歴と OpenAI 管理状態を混在させると、意図的に両レイヤーを調停しない限り、コンテキスト重複が起こる可能性があります。
`result.to_input_list()``session` はクライアント管理です。`conversation_id``previous_response_id` は OpenAI 管理であり、OpenAI Responses API 使用している場合にのみ適用されます。ほとんどのアプリケーションでは、会話ごとに 1 つの永続化戦略を選択してください。クライアント管理履歴と OpenAI 管理状態を混在させると、両方のレイヤーを意図的に調整している場合を除き、コンテキスト重複る可能性があります。
!!! note
Session 永続化、サーバー管理会話設定
(`conversation_id``previous_response_id``auto_previous_response_id`) と
同じ実行内で併用できません。呼び出しごとに 1 つの方を選んでください。
セッションの永続化、サーバー管理会話設定
`conversation_id``previous_response_id`または `auto_previous_response_id`)を
同じ実行で組み合わせることはできません。呼び出しごとにいずれか 1 つの方を選択してください。
### 会話 / チャットスレッド
### 会話チャットスレッド
いずれの run メソッドも、結果として 1 つ以上のエージェント実行 (つまり 1 回以上の LLM 呼び出し) を含む可能性がありますが、チャット会話上は 1 つの論理ターンを表します。例:
いずれの run メソッドを呼び出すと、1 つ以上のエージェント実行される可能性があり、それに伴って LLM が 1 回以上呼び出されますが、これはチャット会話における論理的な 1 ターンを表します。次に例を示します。
1. ユーザーターン: ユーザーがテキスト入力
2. Runner 実行: 最初のエージェントが LLM 呼び出し、ツール実行2 番目エージェントへハンドオフ2 番目エージェントがさらにツール実行し、その後出力を生成
1. ユーザーターンユーザーがテキスト入力します。
2. Runner 実行最初のエージェントが LLM 呼び出し、ツール実行して 2 番目エージェントへハンドオフします。2 番目エージェントがさらにツール実行し、出力を生成します。
エージェント実行の最後に、ユーザー何を表示するかを選ます。えば、エージェントが生成したすべての新規アイテムを表示することも、最終出力だけ表示することもできます。どちらの場合も、その後ユーザーが質問した、run メソッドを再度呼び出せます。
エージェント実行終了時に、ユーザー何を表示するかを選択できます。たとえば、エージェントが生成したすべての新しい項目を表示することも、最終出力のみを表示することもできます。いずれの場合も、ユーザーが続けて質問した場合は、run メソッドを再度呼び出せます。
#### 手動会話管理
#### 手動による会話管理
[`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] メソッドを使て次ターン入力を取得し、会話履歴を手動管理できます。
[`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] メソッドを使用して次ターン入力を取得し、会話履歴を手動管理できます。
```python
async def main():
@@ -267,9 +322,9 @@ async def main():
# California
```
#### Sessions による自動会話管理
#### セッションによる自動会話管理
より簡単な方法として、[Sessions](sessions/index.md) を使うと `.to_input_list()` を手動で呼ばずに会話履歴を自動処理できます。
より簡単な方法として、[Sessions](sessions/index.md) を使用すると、`.to_input_list()` を手動で呼び出すことなく、会話履歴を自動的に処理できます。
```python
from agents import Agent, Runner, SQLiteSession
@@ -293,23 +348,24 @@ async def main():
# California
```
Sessions は自動的に次を行います。
Sessions は次の処理を自動的に行います。
- 各実行前に会話履歴を取得
- 各実行後に新メッセージを保存
- session ID ごとに別の会話を維持
- 各実行前に会話履歴を取得します。
- 各実行後に新しいメッセージを保存します。
- セッション ID ごとに別の会話を維持します。
詳細[Sessions ドキュメント](sessions/index.md) を参照してください。
詳細については、[Sessions ドキュメント](sessions/index.md)を参照してください。
#### サーバー管理会話
`to_input_list()``Sessions` でローカル処理する代わりに、OpenAI conversation state 機能でサーバー側会話状態を管理することもできます。これにより、過去メッセージを毎回手動で再送せずに会話履歴を保持できます。以下のいずれのサーバー管理方式でも、各リクエストでは新規ターン入力のみを渡し、保存済み ID を再利用します。詳細は [OpenAI Conversation state guide](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses) を参照してください。
#### サーバー管理の会話
OpenAI はターン間状態追跡の方法を 2 つ提供します
`to_input_list()` または `Sessions` を使用してローカルで処理する代わりに、OpenAI の会話状態機能にサーバー側で会話状態を管理させることもできます。これにより、過去のすべてのメッセージを毎回手動で再送信することなく、会話履歴を維持できます。以下のいずれかのサーバー管理方式では、各リクエストで新しいターンの入力のみを渡し、保存した ID を再利用します。詳細については、[OpenAI の会話状態ガイド](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses)を参照してください
OpenAI は、ターンをまたいで状態を追跡する 2 つの方法を提供します。
##### 1. `conversation_id` の使用
最初に OpenAI Conversations API 会話を作成し、その ID を以降のすべての呼び出しで再利用します。
まず OpenAI Conversations API を使用して会話を作成し、その後の各呼び出しで ID を再利用します。
```python
from agents import Agent, Runner
@@ -332,7 +388,7 @@ async def main():
##### 2. `previous_response_id` の使用
もう 1 つは **response chaining**各ターンを前ターンの response ID に明示的に連結します。
もう 1 つの方法**レスポンスチェーン**す。各ターンを前ターンのレスポンス ID に明示的に関連付けます。
```python
from agents import Agent, Runner
@@ -357,33 +413,30 @@ async def main():
print(f"Assistant: {result.final_output}")
```
実行が承認待ちで一時停止し、[`RunState`][agents.run_state.RunState] から再開する場合、
SDK は保存済みの `conversation_id` / `previous_response_id` / `auto_previous_response_id`
設定を保持するため、再開ターンも同じサーバー管理会話で継続されます。
実行が承認待ちで一時停止し、[`RunState`][agents.run_state.RunState] から再開した場合、SDK は保存された `conversation_id` / `previous_response_id` / `auto_previous_response_id` の設定を保持するため、再開したターンは同じサーバー管理の会話内で継続されます。
`conversation_id``previous_response_id`排他的です。システム間で共有可能な名前付き会話リソースが必要な`conversation_id` を使ます。ターン間で最も軽量な Responses API 継続プリミティブが必要なら `previous_response_id` を使ます。
`conversation_id``previous_response_id`同時に使用できません。システム間で共有できる名前付き会話リソースが必要な場合は、`conversation_id` を使用します。ターン間で最も軽量な Responses API 継続用基本コンポーネントが必要な場合は、`previous_response_id` を使用します。
!!! note
SDK は `conversation_locked` エラーをバックオフ付きで自動リトライします。サーバー管理
会話実行では、リトライ前に内部 conversation-tracker 入力を巻き戻し、同じ
準備済みアイテムを重複なく再送できるようにします。
SDK は `conversation_locked` エラーをバックオフ付きで自動的に再試行します。サーバー管理
会話を使用する実行では、同じ準備済み項目を問題なく再送信できるよう、再試行前に内部の
conversation tracker の入力を巻き戻します。
ローカルな session ベース実行 (`conversation_id`
`previous_response_id``auto_previous_response_id` とは併用不可) でも、SDK は
リトライ後の履歴重複を減らすため、直近永続化た入力アイテムのベストエフォート
ロールバックを行います。
ローカルのセッションに基づく実行(`conversation_id``previous_response_id`
`auto_previous_response_id` のいずれとも組み合わせられません)でも、SDK は再試行後に
履歴項目が重複することを抑えるため、直近永続化された入力項目のロールバックを可能な範囲で行います。
この互換性リトライは `ModelSettings.retry` 設定でも実行されます。model リクエストに対する
より広い opt-in リトライ挙動は、[Runner 管理リトライ](models/index.md#runner-managed-retries) を参照してください。
この互換性維持のための再試行は、`ModelSettings.retry` 設定していない場合でも行われます。
モデルリクエストに対する、より広範なオプトインの再試行動作については、[Runner 管理の再試行](models/index.md#runner-managed-retries)を参照してください。
## フックとカスタマイズ
### call model input filter
### モデル呼び出しの入力フィルター
`call_model_input_filter` を使うと、model 呼び出し直前の model 入力を編集できます。この hook は現在のエージェント、context、および (存在する場合は session 履歴を含む) 結合済み入力アイテムを受け取り、新しい `ModelInputData` を返します。
モデル呼び出しの直前にモデル入力を編集するには、`call_model_input_filter` を使用します。このフックは、現在のエージェント、コンテキスト、および統合された入力項目(存在する場合はセッション履歴を含む)を受け取り、新しい `ModelInputData` を返します。
り値は [`ModelInputData`][agents.run.ModelInputData] オブジェクトである必要があります。`input` フィールドは必須で、入力アイテムのリストでなければなりません。それ以外の形を返すと `UserError` が発生します。
り値は [`ModelInputData`][agents.run.ModelInputData] オブジェクトである必要があります。その `input` フィールドは必須で、入力項目のリストでなければなりません。それ以外の形を返すと `UserError` が発生します。
```python
from agents import Agent, Runner, RunConfig
@@ -402,19 +455,19 @@ result = Runner.run_sync(
)
```
Runner は準備済み入力リストのコピーを hook に渡すため、呼び出し元の元リストをインプレース変更せずに、トリミング / 置換 / 並べ替えができます。
runner は準備済み入力リストのコピーをフックに渡すため、呼び出し元の元リストを直接変更することなく、短縮、置換、並べ替えを行えます。
session を使っている場合、`call_model_input_filter` session 履歴の読み込みと現在ターンへのマージが完了した後に実行されます。より前段のマージ処理自体をカスタマイズしたい場合は [`session_input_callback`][agents.run.RunConfig.session_input_callback] を使ってください
セッションを使用している場合、`call_model_input_filter`セッション履歴がすでに読み込まれ、現在ターンマージされた後に実行されます。この前段のマージ処理自体をカスタマイズする場合は[`session_input_callback`][agents.run.RunConfig.session_input_callback] を使用します
`conversation_id``previous_response_id``auto_previous_response_id` を使った OpenAI サーバー管理会話状態を使う場合、この hook は次の Responses API 呼び出し向けに準備された payload に対して実行されます。その payload は、過去履歴の完全再送ではなく新規ターン差分のみを表すことがあります。サーバー管理継続送信済みとして扱われるのは、あなたが返したアイテムだけです。
`conversation_id``previous_response_id`または `auto_previous_response_id` を使用して OpenAI サーバー管理会話状態を利用している場合、フックは次の Responses API 呼び出しに準備されたペイロードに対して実行されます。そのペイロードは、以前の履歴全体の再現ではなく、新しいターン差分のみをすでに表している場合があります。返された項目だけが、そのサーバー管理継続処理に送信済みとしてマークされます。
データのマスキング、長い履歴のトリミング、追加システムガイダンスの注入には、`run_config` で実行単位にこの hook を設定してください
データの編集、長い履歴の短縮、追加システムガイダンスの挿入を行うには、`run_config` を介して実行ごとにフックを設定します
## エラーと復旧
### エラーハンドラー
すべての `Runner` エントリーポイントは、エラー種別をキーに持つ dict `error_handlers` を受け付けます。現在サポートされるキーは `"max_turns"` です。`MaxTurnsExceeded` を送出せず、制御された最終出力を返したい場合に使ます。
すべての `Runner` エントリーポイントは、エラー種別をキーとする dict `error_handlers` を受け取ります。サポートされているキーは `"max_turns"``"model_refusal"``"invalid_final_output"` です。対応するエラーで実行を終了する代わりに、制御された最終出力を返場合に使用します。
```python
from agents import (
@@ -443,35 +496,101 @@ result = Runner.run_sync(
print(result.final_output)
```
フォールバック出力を会話履歴に追加したくない場合は `include_in_history=False` を設定します。
モデルメッセージがエージェントの structured な `output_type` に対する検証に失敗した場合、またはモデルが structured な最終メッセージを返さない場合は`"invalid_final_output"` を使用します。ハンドラーはアプリケーション固有のフォールバックを返すことができ、SDK は同じ `output_type` に対してそれを検証します。モデル呼び出しの再試行や、ツールの副作用の再実行は行いません。`None` を返すと、復旧を行いません。フォールバックがない場合、空でないレスポンスの検証失敗では引き続き `ModelBehaviorError` が発生し、空の structured レスポンスでは既存の次ターンの動作が維持されます。
## Durable execution 連携と human-in-the-loop
```python
from pydantic import BaseModel
ツール承認の一時停止 / 再開パターンは、専用の [Human-in-the-loop ガイド](human_in_the_loop.md) から始めてください。
以下の連携は、長時間待機、リトライ、プロセス再起動をまたぐ可能性がある Durable なオーケストレーション向けです。
from agents import Agent, ModelBehaviorError, RunErrorHandlerInput, Runner
class Recipe(BaseModel):
ingredients: list[str]
recovered_from_invalid_output: bool = False
def on_invalid_final_output(data: RunErrorHandlerInput[None]) -> Recipe:
assert isinstance(data.error, ModelBehaviorError)
return Recipe(ingredients=[], recovered_from_invalid_output=True)
agent = Agent(
name="Recipe assistant",
instructions="Return a structured recipe.",
output_type=Recipe,
)
result = Runner.run_sync(
agent,
"Plan tonight's dinner.",
error_handlers={"invalid_final_output": on_invalid_final_output},
)
print(result.final_output)
```
フォールバック出力を会話履歴に追加しない場合は、`include_in_history=False` を設定します。
モデルによる拒否が発生した際に、`ModelRefusalError` で実行を終了する代わりにアプリケーション固有のフォールバックを生成する場合は、`"model_refusal"` を使用します。
```python
from pydantic import BaseModel
from agents import Agent, ModelRefusalError, RunErrorHandlerInput, Runner
class Recipe(BaseModel):
ingredients: list[str]
refusal_reason: str | None = None
def on_model_refusal(data: RunErrorHandlerInput[None]) -> Recipe:
assert isinstance(data.error, ModelRefusalError)
return Recipe(ingredients=[], refusal_reason=data.error.refusal)
agent = Agent(
name="Recipe assistant",
instructions="Return a structured recipe.",
output_type=Recipe,
)
result = Runner.run_sync(
agent,
"Make me something unsafe.",
error_handlers={"model_refusal": on_model_refusal},
)
print(result.final_output)
```
## 永続的な実行の統合とヒューマンインザループ
ツール承認の一時停止/再開パターンについては、専用の[ヒューマンインザループガイド](human_in_the_loop.md)から参照してください。以下の統合は、実行が長時間の待機、再試行、プロセスの再起動にまたがる可能性がある場合の永続的なオーケストレーションを目的としています。
### Dapr
Agents SDK の [Dapr](https://dapr.io) Diagrid 統合を使用すると、ヒューマンインザループをサポートし、障害から自動的に復旧する、永続的かつ長時間実行されるエージェントを実行できます。Dapr はベンダー中立の [CNCF](https://cncf.io) ワークフローオーケストレーターです。Dapr と OpenAI エージェントの使用を開始するには、[こちら](https://docs.diagrid.io/getting-started/quickstarts/ai-agents/?agentframework=openai)を参照してください。
### Temporal
Agents SDK の [Temporal](https://temporal.io/) 連携を使うと、human-in-the-loop タスクを含む Durable で長時間実行ワークフローを実行できます。Temporal と Agents SDK が連携して長時間タスクを完了するデモ[この動画](https://www.youtube.com/watch?v=fFBZqzT4DD8) を参照しドキュメントは [こちら](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents) を参照してください
Agents SDK の [Temporal](https://temporal.io/) 統合を使用すると、ヒューマンインザループのタスクを含む、永続的で長時間実行されるワークフローを実行できます。Temporal と Agents SDK が連携して長時間実行タスクを完了するデモについては、[この動画](https://www.youtube.com/watch?v=fFBZqzT4DD8)を参照してください。また、[ドキュメントはこちら](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)から確認できます
### Restate
Agents SDK の [Restate](https://restate.dev/) 連携を使うと、human approval、ハンドオフ、session 管理を含む軽量で Durable なエージェントを実行できます。この連携には依存関係として Restate の single-binary runtime が必要で、エージェントを process / container または serverless function として実行できます
詳細は [概要](https://www.restate.dev/blog/durable-orchestration-for-ai-agents-with-restate-and-openai-sdk) または [ドキュメント](https://docs.restate.dev/ai) を参照してください。
Agents SDK の [Restate](https://restate.dev/) 統合を使用すると、人による承認、ハンドオフ、セッション管理を含む軽量で永続的なエージェントを利用できます。この統合では、Restate の単一バイナリランタイムが依存関係として必要です。また、エージェントをプロセス/コンテナまたはサーバーレス関数として実行できます。詳細については、[概要](https://www.restate.dev/blog/durable-orchestration-for-ai-agents-with-restate-and-openai-sdk)または[ドキュメント](https://docs.restate.dev/ai)を参照してください
### DBOS
Agents SDK の [DBOS](https://dbos.dev/) 連携を使うと、障害や再起動をまたいで進行状況を保持する信頼性の高いエージェントを実行できます。長時間実行エージェント、human-in-the-loop ワークフロー、ハンドオフをサポートします。同期 / 非同期メソッドの両方をサポートします。この連携に必要なのは SQLite または Postgres データベースのみです。詳細は連携 [repo](https://github.com/dbos-inc/dbos-openai-agents)[ドキュメント](https://docs.dbos.dev/integrations/openai-agents) を参照してください。
Agents SDK の [DBOS](https://dbos.dev/) 統合を使用すると、障害や再起動が発生しても進行状況を保持する信頼性の高いエージェントを実行できます。長時間実行されるエージェント、ヒューマンインザループのワークフロー、ハンドオフをサポートします。同期メソッドと非同期メソッドの両方に対応しています。この統合に必要なのはSQLite または Postgres データベースのみです。詳細については、統合の[リポジトリ](https://github.com/dbos-inc/dbos-openai-agents)[ドキュメント](https://docs.dbos.dev/integrations/openai-agents)を参照してください。
## 例外
SDK は特定のケースで例外を送出します。完全な一覧は [`agents.exceptions`][] にあります。概要は次のとおりです。
SDK は特定の状況で例外を発生させます。完全な一覧は [`agents.exceptions`][] にあります。概要は次のとおりです。
- [`AgentsException`][agents.exceptions.AgentsException]: SDK 内で送出されるすべての例外の基底クラスです。ほかのすべての具体例外がこの型から派生します。
- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]: エージェント実行が `Runner.run``Runner.run_sync``Runner.run_streamed` に渡し`max_turns` 限を超えたときに送出されます。指定された対話ターン数内でタスクを完了できなかったことを示します。
- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]: 基盤 model (LLM) が予期しないまたは無効な出力を生成したときに発生ます。例:
- 不正な JSON: ツール呼び出し用、または直接出力内の JSON 構造が不正な場合。特に特定の `output_type` が定義されている場合
- 想定外のツール関連失敗: model が想定どおりにツールを使えない場合
- [`ToolTimeoutError`][agents.exceptions.ToolTimeoutError]: 関数ツール呼び出しが設定タイムアウトを超過し、ツールが `timeout_behavior="raise_exception"` を使ている場合に送出されます。
- [`UserError`][agents.exceptions.UserError]: SDK 使用中に、あなた (SDK を使ってコードを書く人) が誤りをしたときに送出されます。通常はコード実装不備、無効な設定、または SDK API の誤用が原因です。
- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]: 入力ガードレールまたは出力ガードレールの条件が満たされたときに、それぞれ送出されます。入力ガードレールは処理前受信メッセージを検査し、出力ガードレールは配信前エージェント最終応答を検査します。
- [`AgentsException`][agents.exceptions.AgentsException]SDK 内で発生するすべての例外の基底クラスです。のすべての具体的な例外は、この汎用型から派生します。
- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]エージェント実行が`Runner.run``Runner.run_sync`または `Runner.run_streamed` メソッドに渡され`max_turns` 限を超えた場合に発生する例外です。指定された対話ターン数以内にエージェントがタスクを完了できなかったことを示します。制限を無効にするには、`max_turns=None` を設定します。
- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]:基盤となるモデル(LLMが予期しない出力または無効な出力を生成した場合に発生する例外です。これには次のものが含まれます。
- 不正な JSON:特に特定の `output_type` が定義されている場合に、モデルがツール呼び出しまたは直接出力で不正な JSON 構造を返した場合です
- 予期しないツール関連失敗:モデルが想定された方法でツールを使用できなかった場合です。
- [`ToolTimeoutError`][agents.exceptions.ToolTimeoutError]関数ツール呼び出しが設定されたタイムアウトを超え、そのツールが `timeout_behavior="raise_exception"` を使用している場合に発生する例外です。
- [`UserError`][agents.exceptions.UserError]SDK 使用するコードを作成しているユーザーが、SDK の使用時に誤りをした場合に発生する例外です。通常は、不適切なコード実装、無効な設定、SDK API の誤用によって発生します。
- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered][`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]:それぞれ、入力ガードレールまたは出力ガードレールの条件が満たされた場合に発生する例外です。入力ガードレールは処理前受信メッセージをチェックし、出力ガードレールは配信前エージェント最終レスポンスをチェックします。
+141
View File
@@ -0,0 +1,141 @@
---
search:
exclude: true
---
# サンドボックスクライアント
このページでは、サンドボックスでの作業をどこで実行するかを選択します。ほとんどの場合、`SandboxAgent` の定義は同じままにし、サンドボックスクライアントとクライアント固有のオプションを [`SandboxRunConfig`][agents.run_config.SandboxRunConfig] で変更します。
!!! warning "ベータ機能"
サンドボックスエージェントはベータ版です。一般提供までに API の詳細、デフォルト値、サポートされる機能が変更される可能性があります。また、時間とともにより高度な機能が追加される見込みです。
## 判断ガイド
<div class="sandbox-nowrap-first-column-table" markdown="1">
| 目的 | まず使うもの | 理由 |
| --- | --- | --- |
| macOS または Linux での最速のローカル反復 | `UnixLocalSandboxClient` | 追加インストール不要で、シンプルなローカルファイルシステム開発ができます。 |
| 基本的なコンテナ分離 | `DockerSandboxClient` | 特定のイメージを使って Docker 内で作業を実行します。 |
| ホスト型実行または本番環境スタイルの分離 | ホスト型サンドボックスクライアント | ワークスペース境界をプロバイダー管理環境へ移します。 |
</div>
## ローカルクライアント
ほとんどのユーザーは、これら 2 つのサンドボックスクライアントのいずれかから始めることをおすすめします。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| クライアント | インストール | 選ぶ場面 | 例 |
| --- | --- | --- | --- |
| `UnixLocalSandboxClient` | なし | macOS または Linux で最速のローカル反復が必要な場合。ローカル開発の既定として適しています。 | [Unix-local スターター](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/unix_local_runner.py) |
| `DockerSandboxClient` | `openai-agents[docker]` | コンテナ分離、またはローカルで同等性を保つための特定のイメージが必要な場合。 | [Docker スターター](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docker/docker_runner.py) |
</div>
Unix-local は、ローカルファイルシステムに対して開発を始める最も簡単な方法です。より強い環境分離や本番環境スタイルの同等性が必要になったら、Docker またはホスト型プロバイダーへ移行してください。
Unix-local から Docker に切り替えるには、エージェント定義は同じままにして、実行設定だけを変更します。
```python
from docker import from_env as docker_from_env
from agents.run import RunConfig
from agents.sandbox import SandboxRunConfig
from agents.sandbox.sandboxes.docker import DockerSandboxClient, DockerSandboxClientOptions
run_config = RunConfig(
sandbox=SandboxRunConfig(
client=DockerSandboxClient(docker_from_env()),
options=DockerSandboxClientOptions(image="python:3.14-slim"),
),
)
```
コンテナ分離またはイメージの同等性が必要な場合に使用してください。[examples/sandbox/docker/docker_runner.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docker/docker_runner.py) を参照してください。
## マウントとリモートストレージ
マウントエントリーはどのストレージを公開するかを表し、マウント戦略はサンドボックスバックエンドがそのストレージをどのようにアタッチするかを表します。組み込みのマウントエントリーと汎用戦略は `agents.sandbox.entries` からインポートします。ホスト型プロバイダーの戦略は `agents.extensions.sandbox` またはプロバイダー固有の拡張パッケージから利用できます。
一般的なマウントオプション:
- `mount_path`: ストレージがサンドボックス内で表示される場所です。相対パスはマニフェストルート配下で解決され、絶対パスはそのまま使用されます。
- `read_only`: 既定は `True` です。サンドボックスがマウントされたストレージへ書き戻す必要がある場合にのみ `False` に設定してください。
- `mount_strategy`: 必須です。マウントエントリーとサンドボックスバックエンドの両方に合う戦略を使用してください。
マウントは一時的なワークスペースエントリーとして扱われます。スナップショットと永続化のフローでは、マウントされたリモートストレージを保存済みワークスペースへコピーするのではなく、マウントされたパスをデタッチするかスキップします。
汎用ローカル / コンテナ戦略:
<div class="sandbox-nowrap-first-column-table" markdown="1">
| 戦略またはパターン | 使用する場面 | 備考 |
| --- | --- | --- |
| `InContainerMountStrategy(pattern=RcloneMountPattern(...))` | サンドボックスイメージで `rclone` を実行できる場合。 | S3、GCS、R2、Azure Blob、Box をサポートします。`RcloneMountPattern``fuse` モードまたは `nfs` モードで実行できます。 |
| `InContainerMountStrategy(pattern=MountpointMountPattern(...))` | イメージに `mount-s3` があり、Mountpoint スタイルの S3 または S3 互換アクセスが必要な場合。 | `S3Mount``GCSMount` をサポートします。 |
| `InContainerMountStrategy(pattern=FuseMountPattern(...))` | イメージに `blobfuse2` があり、FUSE サポートがある場合。 | `AzureBlobMount` をサポートします。 |
| `InContainerMountStrategy(pattern=S3FilesMountPattern(...))` | イメージに `mount.s3files` があり、既存の S3 Files マウントターゲットに到達できる場合。 | `S3FilesMount` をサポートします。 |
| `DockerVolumeMountStrategy(driver=...)` | Docker がコンテナ起動前にボリュームドライバー対応のマウントをアタッチする必要がある場合。 | Docker のみです。`rclone` は S3、GCS、R2、Azure Blob、Box をサポートし、`mountpoint` は S3 と GCS もサポートします。 |
</div>
## サポートされるホスト型プラットフォーム
ホスト型環境が必要な場合、通常は同じ `SandboxAgent` 定義をそのまま引き継ぎ、[`SandboxRunConfig`][agents.run_config.SandboxRunConfig] でサンドボックスクライアントだけを変更します。
このリポジトリのチェックアウトではなく公開されている SDK を使用している場合は、対応するパッケージ extra を通じてサンドボックスクライアントの依存関係をインストールしてください。
プロバイダー固有のセットアップメモと、チェックイン済みの拡張コード例へのリンクについては、[examples/sandbox/extensions/README.md](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/README.md) を参照してください。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| クライアント | インストール | 例 |
| --- | --- | --- |
| `BlaxelSandboxClient` | `openai-agents[blaxel]` | [Blaxel ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/blaxel_runner.py) |
| `CloudflareSandboxClient` | `openai-agents[cloudflare]` | [Cloudflare ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/cloudflare_runner.py) |
| `DaytonaSandboxClient` | `openai-agents[daytona]` | [Daytona ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/daytona/daytona_runner.py) |
| `E2BSandboxClient` | `openai-agents[e2b]` | [E2B ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/e2b_runner.py) |
| `ModalSandboxClient` | `openai-agents[modal]` | [Modal ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/modal_runner.py) |
| `RunloopSandboxClient` | `openai-agents[runloop]` | [Runloop ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/runloop/runner.py) |
| `VercelSandboxClient` | `openai-agents[vercel]` | [Vercel ランナー](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/vercel_runner.py) |
</div>
ホスト型サンドボックスクライアントは、プロバイダー固有のマウント戦略を公開します。ストレージプロバイダーに最も合うバックエンドとマウント戦略を選択してください。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| バックエンド | マウントに関する注記 |
| --- | --- |
| Docker | `InContainerMountStrategy``DockerVolumeMountStrategy` などのローカル戦略で、`S3Mount``GCSMount``R2Mount``AzureBlobMount``BoxMount``S3FilesMount` をサポートします。 |
| `ModalSandboxClient` | `S3Mount``R2Mount`、HMAC 認証済みの `GCSMount` で、`ModalCloudBucketMountStrategy` による Modal のクラウドバケットマウントをサポートします。インライン認証情報、または名前付きの Modal Secret を使用できます。 |
| `CloudflareSandboxClient` | `S3Mount``R2Mount`、HMAC 認証済みの `GCSMount` で、`CloudflareBucketMountStrategy` による Cloudflare バケットマウントをサポートします。 |
| `BlaxelSandboxClient` | `S3Mount``R2Mount``GCSMount` で、`BlaxelCloudBucketMountStrategy` によるクラウドバケットマウントをサポートします。`agents.extensions.sandbox.blaxel``BlaxelDriveMount``BlaxelDriveMountStrategy` による永続的な Blaxel Drives もサポートします。 |
| `DaytonaSandboxClient` | `DaytonaCloudBucketMountStrategy` による `rclone` ベースのクラウドストレージマウントをサポートします。`S3Mount``GCSMount``R2Mount``AzureBlobMount``BoxMount` と組み合わせて使用してください。 |
| `E2BSandboxClient` | `E2BCloudBucketMountStrategy` による `rclone` ベースのクラウドストレージマウントをサポートします。`S3Mount``GCSMount``R2Mount``AzureBlobMount``BoxMount` と組み合わせて使用してください。 |
| `RunloopSandboxClient` | `RunloopCloudBucketMountStrategy` による `rclone` ベースのクラウドストレージマウントをサポートします。`S3Mount``GCSMount``R2Mount``AzureBlobMount``BoxMount` と組み合わせて使用してください。 |
| `VercelSandboxClient` | 現時点ではホスト型固有のマウント戦略は公開されていません。代わりにマニフェストファイル、リポジトリ、またはその他のワークスペース入力を使用してください。 |
</div>
以下の表は、各バックエンドが直接マウントできるリモートストレージエントリーをまとめたものです。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| バックエンド | AWS S3 | Cloudflare R2 | GCS | Azure Blob Storage | Box | S3 Files |
| --- | --- | --- | --- | --- | --- | --- |
| Docker | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `ModalSandboxClient` | ✓ | ✓ | ✓ | - | - | - |
| `CloudflareSandboxClient` | ✓ | ✓ | ✓ | - | - | - |
| `BlaxelSandboxClient` | ✓ | ✓ | ✓ | - | - | - |
| `DaytonaSandboxClient` | ✓ | ✓ | ✓ | ✓ | ✓ | - |
| `E2BSandboxClient` | ✓ | ✓ | ✓ | ✓ | ✓ | - |
| `RunloopSandboxClient` | ✓ | ✓ | ✓ | ✓ | ✓ | - |
| `VercelSandboxClient` | - | - | - | - | - | - |
</div>
実行可能なコード例をさらに見るには、ローカル、コーディング、メモリ、ハンドオフ、エージェント合成パターンについては [examples/sandbox/](https://github.com/openai/openai-agents-python/tree/main/examples/sandbox) を、ホスト型サンドボックスクライアントについては [examples/sandbox/extensions/](https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/extensions) を参照してください。
+861
View File
@@ -0,0 +1,861 @@
---
search:
exclude: true
---
# 概念
!!! warning "ベータ機能"
サンドボックスエージェントはベータ版です。一般提供までに API の詳細、デフォルト、サポートされる機能が変更される可能性があります。また、今後さらに高度な機能が追加される予定です。
最新のエージェントは、ファイルシステム上の実際のファイルを操作できる場合に最も効果を発揮します。**サンドボックスエージェント**は、特化したツールやシェルコマンドを使用して、大規模なドキュメントセットの検索や操作、ファイルの編集、成果物の生成、コマンドの実行を行えます。サンドボックスは、エージェントがユーザーに代わって作業するために利用できる永続的なワークスペースをモデルに提供します。Agents SDK のサンドボックスエージェントを使用すると、サンドボックス環境と組み合わせたエージェントを簡単に実行できます。また、適切なファイルをファイルシステム上に配置し、サンドボックスをオーケストレーションすることで、大規模なタスクの開始、停止、再開を容易に行えます。
エージェントが必要とするデータを中心にワークスペースを定義します。GitHub リポジトリ、ローカルのファイルやディレクトリ、合成タスクファイル、S3 や Azure Blob Storage などのリモートファイルシステム、および提供するその他のサンドボックス入力から開始できます。
<div class="sandbox-harness-image" markdown="1">
![コンピューティング機能を備えたサンドボックスエージェントハーネス](../assets/images/harness_with_compute.png)
</div>
`SandboxAgent` も引き続き `Agent` です。`instructions``prompt``tools``handoffs``mcp_servers``model_settings``output_type`、ガードレール、フックなど、通常のエージェントインターフェースを維持し、通常の `Runner` API を通じて実行されます。異なるのは実行境界です。
- `SandboxAgent` はエージェント自体を定義します。通常のエージェント設定に加えて、`default_manifest``base_instructions``run_as` などのサンドボックス固有のデフォルト、およびファイルシステムツール、シェルアクセス、スキル、メモリ、コンパクションなどの機能を含みます。
- `Manifest` は、ファイル、リポジトリ、マウント、環境など、新しいサンドボックスワークスペースの初期内容とレイアウトを宣言します。
- サンドボックスセッションは、コマンドが実行され、ファイルが変更される稼働中の分離環境です。
- [`SandboxRunConfig`][agents.run_config.SandboxRunConfig] は、サンドボックスセッションを直接注入する、シリアライズされたサンドボックスセッション状態から再接続する、サンドボックスクライアントを通じて新しいサンドボックスセッションを作成するなど、実行がサンドボックスセッションを取得する方法を決定します。
- 保存されたサンドボックス状態とスナップショットにより、後続の実行は以前の作業へ再接続したり、保存された内容を使用して新しいサンドボックスセッションを初期化したりできます。
`Manifest` は新規セッション用のワークスペース契約であり、稼働中のすべてのサンドボックスに関する完全な信頼できる情報源ではありません。実行時に有効となるワークスペースは、再利用されたサンドボックスセッション、シリアライズされたサンドボックスセッション状態、または実行時に選択されたスナップショットから取得される場合があります。
このページでは、「サンドボックスセッション」はサンドボックスクライアントによって管理される稼働中の実行環境を意味します。これは、[セッション](../sessions/index.md)で説明されている SDK の会話用 [`Session`][agents.memory.session.Session] インターフェースとは異なります。
外側のランタイムは、引き続き承認、トレーシング、ハンドオフ、再開時の記録管理を担います。サンドボックスセッションは、コマンド、ファイル変更、環境の分離を担います。この分担は、このモデルの中核をなす要素です。
### 各要素の連携
サンドボックス実行では、エージェント定義と実行ごとのサンドボックス設定を組み合わせます。ランナーはエージェントを準備して稼働中のサンドボックスセッションにバインドし、後続の実行のために状態を保存できます。
```mermaid
flowchart LR
agent["SandboxAgent<br/><small>full Agent + sandbox defaults</small>"]
config["SandboxRunConfig<br/><small>client / session / resume inputs</small>"]
runner["Runner<br/><small>prepare instructions<br/>bind capability tools</small>"]
sandbox["sandbox session<br/><small>workspace where commands run<br/>and files change</small>"]
saved["saved state / snapshot<br/><small>for resume or fresh-start later</small>"]
agent --> runner
config --> runner
runner --> sandbox
sandbox --> saved
```
サンドボックス固有のデフォルトは `SandboxAgent` に保持します。実行ごとのサンドボックスセッションの選択は `SandboxRunConfig` に保持します。
ライフサイクルは、次の 3 段階で考えます。
1. `SandboxAgent``Manifest`、機能を使用して、エージェントと新規ワークスペースの契約を定義します。
2. サンドボックスセッションを注入、再開、または作成する `SandboxRunConfig``Runner` に渡して実行します。
3. ランナーが管理する `RunState`、明示的なサンドボックスの `session_state`、または保存済みワークスペースのスナップショットから、後で処理を継続します。
シェルアクセスがたまにしか使用しないツールの 1 つにすぎない場合は、[ツールガイド](../tools.md)のホステッドシェルから始めてください。ワークスペースの分離、サンドボックスクライアントの選択、またはサンドボックスセッションの再開動作が設計の一部である場合は、サンドボックスエージェントを使用してください。
## 使用に適した状況
サンドボックスエージェントは、次のようなワークスペース中心のワークフローに適しています。
- コーディングとデバッグ。たとえば、GitHub リポジトリの Issue レポートに対する自動修正をオーケストレーションし、対象を絞ったテストを実行する場合
- ドキュメントの処理と編集。たとえば、ユーザーの財務書類から情報を抽出し、記入済みの税務フォームの下書きを作成する場合
- ファイルを根拠とするレビューや分析。たとえば、回答前にオンボーディング資料、生成されたレポート、成果物のバンドルを確認する場合
- 分離されたマルチエージェントパターン。たとえば、各レビュアーやコーディング用サブエージェントに専用のワークスペースを提供する場合
- 複数ステップのワークスペースタスク。たとえば、ある実行でバグを修正し、後で回帰テストを追加する場合や、スナップショットまたはサンドボックスセッション状態から再開する場合
ファイルや稼働中のファイルシステムへのアクセスが不要な場合は、引き続き `Agent` を使用してください。シェルアクセスがたまにしか使用しない機能の 1 つであればホステッドシェルを追加し、ワークスペース境界自体が機能の一部であればサンドボックスエージェントを使用します。
## サンドボックスクライアントの選択
ローカル開発では `UnixLocalSandboxClient` から始めてください。コンテナ分離やイメージの同等性が必要な場合は `DockerSandboxClient` に移行します。プロバイダー管理の実行が必要な場合は、ホステッドプロバイダーに移行します。
ほとんどの場合、`SandboxAgent` の定義はそのまま維持し、[`SandboxRunConfig`][agents.run_config.SandboxRunConfig] 内のサンドボックスクライアントとそのオプションのみを変更します。ローカル、Docker、ホステッド、リモートマウントのオプションについては、[サンドボックスクライアント](clients.md)を参照してください。
## 中核要素
<div class="sandbox-nowrap-first-column-table" markdown="1">
| レイヤー | 主な SDK 要素 | 回答する内容 |
| --- | --- | --- |
| エージェント定義 | `SandboxAgent``Manifest`、機能 | どのエージェントを実行し、どの新規セッション用ワークスペース契約から開始するか? |
| サンドボックス実行 | `SandboxRunConfig`、サンドボックスクライアント、稼働中のサンドボックスセッション | この実行は稼働中のサンドボックスセッションをどのように取得し、作業はどこで実行されるか? |
| 保存済みサンドボックス状態 | `RunState` のサンドボックスペイロード、`session_state`、スナップショット | このワークフローは以前のサンドボックス作業へどのように再接続し、保存された内容から新しいサンドボックスセッションをどのように初期化するか? |
</div>
主な SDK 要素は、次のようにこれらのレイヤーに対応します。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| 要素 | 担当範囲 | 確認すべき内容 |
| --- | --- | --- |
| [`SandboxAgent`][agents.sandbox.sandbox_agent.SandboxAgent] | エージェント定義 | このエージェントは何を実行し、どのデフォルト設定を引き継ぐべきか? |
| [`Manifest`][agents.sandbox.manifest.Manifest] | 新規セッション用ワークスペースのファイルとフォルダー | 実行開始時に、どのファイルとフォルダーがファイルシステム上に存在すべきか? |
| [`Capability`][agents.sandbox.capabilities.capability.Capability] | サンドボックスネイティブの動作 | どのツール、指示フラグメント、ランタイム動作をこのエージェントに付与すべきか? |
| [`SandboxRunConfig`][agents.run_config.SandboxRunConfig] | 実行ごとのサンドボックスクライアントとサンドボックスセッションの取得元 | この実行では、サンドボックスセッションを注入、再開、作成のいずれで取得すべきか? |
| [`RunState`][agents.run_state.RunState] | ランナーが管理する保存済みサンドボックス状態 | 以前のランナー管理ワークフローを再開し、そのサンドボックス状態を自動的に引き継いでいるか? |
| [`SandboxRunConfig.session_state`][agents.run_config.SandboxRunConfig.session_state] | 明示的にシリアライズされたサンドボックスセッション状態 | `RunState` の外部で既にシリアライズしたサンドボックス状態から再開するか? |
| [`SandboxRunConfig.snapshot`][agents.run_config.SandboxRunConfig.snapshot] | 新しいサンドボックスセッション用に保存されたワークスペース内容 | 新しいサンドボックスセッションを保存済みのファイルや成果物から開始するか? |
</div>
実用的な設計順序は次のとおりです。
1. `Manifest` で新規セッション用ワークスペース契約を定義します。
2. `SandboxAgent` でエージェントを定義します。
3. 組み込みまたはカスタムの機能を追加します。
4. `RunConfig(sandbox=SandboxRunConfig(...))` で、各実行がサンドボックスセッションを取得する方法を決定します。
## サンドボックス実行の準備
実行時に、ランナーはその定義を具体的なサンドボックス対応の実行へ変換します。
1. `SandboxRunConfig` からサンドボックスセッションを解決します。`session=...` を渡した場合、その稼働中のサンドボックスセッションを再利用します。それ以外の場合は、`client=...` を使用してセッションを作成または再開します。
2. 実行で有効となるワークスペース入力を決定します。実行でサンドボックスセッションを注入または再開する場合、その既存のサンドボックス状態が優先されます。それ以外の場合、ランナーは一時的なマニフェストオーバーライドまたは `agent.default_manifest` から開始します。このため、`Manifest` だけでは、すべての実行における最終的な稼働中ワークスペースは定義されません。
3. 機能が生成されたマニフェストを処理できるようにします。これにより、最終的なエージェントの準備前に、機能がファイル、マウント、その他のワークスペース単位の動作を追加できます。
4. 最終的な指示を固定された順序で構築します。SDK のデフォルトのサンドボックスプロンプト、または明示的にオーバーライドした場合は `base_instructions`、次に `instructions`、機能の指示フラグメント、リモートマウントのポリシーテキスト、レンダリングされたファイルシステムツリーの順です。
5. 機能ツールを稼働中のサンドボックスセッションにバインドし、準備済みのエージェントを通常の `Runner` API を通じて実行します。
サンドボックス化によって、ターンの意味は変わりません。ターンは引き続きモデルの 1 ステップであり、単一のシェルコマンドやサンドボックス操作ではありません。サンドボックス側の操作とターンの間に固定された 1 対 1 の対応関係はありません。一部の作業はサンドボックス実行レイヤー内に留まる場合がありますが、他の操作ではツールの結果、承認、または別のモデルステップを必要とするその他の状態が返されます。実用上は、サンドボックスで作業が行われた後、エージェントランタイムが別のモデル応答を必要とする場合にのみ、追加のターンが消費されます。
これらの準備手順があるため、`SandboxAgent` を設計する際には、`default_manifest``instructions``base_instructions``capabilities``run_as` が主なサンドボックス固有の検討事項になります。
## `SandboxAgent` のオプション
通常の `Agent` フィールドに加えて、次のサンドボックス固有オプションがあります。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| オプション | 最適な用途 |
| --- | --- |
| `default_manifest` | ランナーが作成する新しいサンドボックスセッション用のデフォルトワークスペース。 |
| `instructions` | SDK のサンドボックスプロンプトの後に追加される、ロール、ワークフロー、成功条件。 |
| `base_instructions` | SDK のサンドボックスプロンプトを置き換える高度なエスケープハッチ。 |
| `capabilities` | このエージェントとともに引き継ぐサンドボックスネイティブのツールと動作。 |
| `run_as` | シェルコマンド、ファイル読み取り、パッチなど、モデル向けサンドボックスツールで使用するユーザー ID。 |
</div>
サンドボックスクライアントの選択、サンドボックスセッションの再利用、マニフェストのオーバーライド、スナップショットの選択は、エージェントではなく [`SandboxRunConfig`][agents.run_config.SandboxRunConfig] に設定します。
### `default_manifest`
`default_manifest` は、ランナーがこのエージェント用に新しいサンドボックスセッションを作成するときに使用するデフォルトの [`Manifest`][agents.sandbox.manifest.Manifest] です。エージェントが通常、開始時に必要とするファイル、リポジトリ、補助資料、出力ディレクトリ、マウントに使用します。
これはデフォルトにすぎません。実行時に `SandboxRunConfig(manifest=...)` でオーバーライドでき、再利用または再開されたサンドボックスセッションは既存のワークスペース状態を維持します。
### `instructions` と `base_instructions`
異なるプロンプト間でも維持すべき短いルールには、`instructions` を使用します。`SandboxAgent` では、これらの指示は SDK のサンドボックス基本プロンプトの後に追加されるため、組み込みのサンドボックスガイダンスを維持しながら、独自のロール、ワークフロー、成功条件を追加できます。
SDK のサンドボックス基本プロンプトを置き換える場合にのみ、`base_instructions` を使用してください。ほとんどのエージェントでは設定しないでください。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| 設定先 | 用途 | 例 |
| --- | --- | --- |
| `instructions` | エージェントの安定したロール、ワークフロールール、成功条件。 | 「オンボーディング書類を確認してから、ハンドオフしてください」、「最終ファイルを `output/` に書き込んでください」。 |
| `base_instructions` | SDK のサンドボックス基本プロンプト全体の置き換え。 | カスタムの低レベルサンドボックスラッパープロンプト。 |
| ユーザープロンプト | この実行に固有のリクエスト。 | 「このワークスペースを要約してください」。 |
| マニフェスト内のワークスペースファイル | 長いタスク仕様、リポジトリローカルの指示、範囲を限定した参考資料。 | `repo/task.md`、ドキュメントバンドル、サンプル資料。 |
</div>
`instructions` の適切な使用例は次のとおりです。
- [examples/sandbox/unix_local_pty.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/unix_local_pty.py) では、PTY の状態が重要な場合に、エージェントを単一の対話型プロセス内に維持します。
- [examples/sandbox/handoffs.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/handoffs.py) では、サンドボックスレビュアーが確認後にユーザーへ直接回答することを禁止します。
- [examples/sandbox/tax_prep.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/tax_prep.py) では、最終的な記入済みファイルが実際に `output/` に配置されることを必須とします。
- [examples/sandbox/docs/coding_task.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docs/coding_task.py) では、正確な検証コマンドを固定し、ワークスペースルート相対のパッチパスを明確にします。
ユーザーの一時的なタスクを `instructions` にコピーすること、マニフェストに置くべき長い参考資料を埋め込むこと、組み込み機能が既に注入するツールドキュメントを繰り返すこと、モデルが実行時に必要としないローカルインストールの注意事項を混在させることは避けてください。
`instructions` を省略しても、SDK はデフォルトのサンドボックスプロンプトを含めます。低レベルのラッパーにはこれで十分ですが、ほとんどのユーザー向けエージェントでは、明示的な `instructions` も指定する必要があります。
### `capabilities`
機能は、サンドボックスネイティブの動作を `SandboxAgent` に付与します。実行開始前にワークスペースを形成し、サンドボックス固有の指示を追加し、稼働中のサンドボックスセッションにバインドされるツールを公開し、そのエージェントのモデル動作や入力処理を調整できます。
組み込み機能には次のものがあります。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| 機能 | 追加する状況 | 注記 |
| --- | --- | --- |
| `Shell` | エージェントにシェルアクセスが必要な場合。 | `exec_command` を追加し、サンドボックスクライアントが PTY 対話をサポートする場合は `write_stdin` も追加します。 |
| `Filesystem` | エージェントがファイルを編集したり、ローカル画像を確認したりする必要がある場合。 | `apply_patch``view_image` を追加します。パッチパスはワークスペースルート相対です。 |
| `Skills` | サンドボックス内でスキルの検出とマテリアライズを行う場合。 | `.agents` または `.agents/skills` を手動でマウントするよりも、こちらを推奨します。`Skills` がスキルのインデックス作成とサンドボックスへのマテリアライズを行います。 |
| `Memory` | 後続の実行でメモリ成果物を読み取り、または生成する必要がある場合。 | `Shell` が必要です。ライブ更新には `Filesystem` も必要です。 |
| `Compaction` | 長時間実行されるフローで、コンパクション項目の後にコンテキストを削減する必要がある場合。 | モデルのサンプリングと入力処理を調整します。 |
</div>
デフォルトでは、`SandboxAgent.capabilities``Capabilities.default()` を使用し、これには `Filesystem()``Shell()``Compaction()` が含まれます。`capabilities=[...]` を渡すと、そのリストがデフォルトを置き換えるため、引き続き必要なデフォルト機能を含めてください。
スキルについては、マテリアライズ方法に応じてソースを選択します。
- `Skills(lazy_from=LocalDirLazySkillSource(...))` は、モデルが最初にインデックスを検出し、必要なものだけを読み込めるため、大規模なローカルスキルディレクトリに適したデフォルトです。
- `LocalDirLazySkillSource(source=LocalDir(src=...))` は、SDK プロセスが実行されているファイルシステムから読み取ります。サンドボックスイメージまたはワークスペース内にのみ存在するパスではなく、元のホスト側スキルディレクトリを渡してください。
- `Skills(from_=LocalDir(src=...))` は、事前にステージングする小規模なローカルバンドルに適しています。
- `Skills(from_=GitRepo(repo=..., ref=...))` は、スキル自体をリポジトリから取得する場合に適しています。
`LocalDir.src` は SDK ホスト上のソースパスです。`skills_path` はサンドボックスワークスペース内の相対的な配置先パスであり、`load_skill` の呼び出し時にスキルがステージングされます。
スキルが既に `.agents/skills/<name>/SKILL.md` のような場所に存在する場合は、そのソースルートを `LocalDir(...)` に指定し、引き続き `Skills(...)` を使用して公開してください。別のサンドボックス内レイアウトに依存する既存のワークスペース契約がない限り、デフォルトの `skills_path=".agents"` を維持してください。
要件に適合する場合は、組み込み機能を優先してください。組み込み機能では対応できないサンドボックス固有のツールや指示インターフェースが必要な場合にのみ、カスタム機能を作成します。
## 概念
### マニフェスト
[`Manifest`][agents.sandbox.manifest.Manifest] は、新しいサンドボックスセッション用のワークスペースを記述します。ワークスペースの `root` の設定、ファイルとディレクトリの宣言、ローカルファイルのコピー、Git リポジトリのクローン、リモートストレージマウントの接続、環境変数の設定、ユーザーやグループの定義、ワークスペース外にある特定の絶対パスへのアクセス許可を行えます。
マニフェストエントリのパスはワークスペース相対です。絶対パスにしたり、`..` を使用してワークスペース外へ移動したりすることはできません。これにより、ローカル、Docker、ホステッドクライアント間でワークスペース契約の移植性が保たれます。
作業開始前にエージェントが必要とする素材には、マニフェストエントリを使用します。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| マニフェストエントリ | 用途 |
| --- | --- |
| `File``Dir` | 小規模な合成入力、補助ファイル、出力ディレクトリ。 |
| `LocalFile``LocalDir` | サンドボックス内にマテリアライズするホストのファイルまたはディレクトリ。 |
| `GitRepo` | ワークスペースに取得するリポジトリ。 |
| `S3Mount``GCSMount``R2Mount``AzureBlobMount``BoxMount``S3FilesMount` などのマウント | サンドボックス内に表示する外部ストレージ。 |
</div>
`Dir` は、合成の子要素からサンドボックスワークスペース内にディレクトリを作成するか、出力先を作成します。ホストのファイルシステムから読み取るものではありません。既存のホストディレクトリをサンドボックスワークスペースへコピーする場合は、`LocalDir` を使用します。
`LocalFile.src``LocalDir.src` は、デフォルトでは SDK プロセスの作業ディレクトリを基準に解決されます。ソースは、`extra_path_grants` の対象でない限り、その基準ディレクトリ内に置く必要があります。これにより、ローカルソースのマテリアライズは、サンドボックスマニフェストの他の部分と同じホストパスの信頼境界内に保たれます。
マウントエントリは公開するストレージを記述し、マウント戦略はサンドボックスバックエンドがそのストレージを接続する方法を記述します。マウントオプションとプロバイダーのサポートについては、[サンドボックスクライアント](clients.md#mounts-and-remote-storage)を参照してください。
適切なマニフェスト設計では通常、ワークスペース契約を必要最小限に保ち、長いタスク手順を `repo/task.md` などのワークスペースファイルに配置し、指示内では `repo/task.md``output/report.md` などのワークスペース相対パスを使用します。エージェントが `Filesystem` 機能の `apply_patch` ツールでファイルを編集する場合、パッチパスはシェルの `workdir` ではなく、サンドボックスワークスペースのルートからの相対パスであることに注意してください。
エージェントがワークスペース外の具体的な絶対パスを必要とする場合、またはマニフェストが SDK プロセスの作業ディレクトリ外にある信頼済みローカルソースをコピーする必要がある場合にのみ、`extra_path_grants` を使用してください。例としては、一時的なツール出力用の `/tmp`、読み取り専用ランタイム用の `/opt/toolchain`、サンドボックス内にマテリアライズする生成済みスキルディレクトリなどがあります。許可は、ローカルソースのマテリアライズ、SDK のファイル API、およびバックエンドがファイルシステムポリシーを適用できる場合のシェル実行に適用されます。
```python
from agents.sandbox import Manifest, SandboxPathGrant
manifest = Manifest(
extra_path_grants=(
SandboxPathGrant(path="/tmp"),
SandboxPathGrant(path="/opt/toolchain", read_only=True),
),
)
```
`extra_path_grants` を含むマニフェストは、信頼済み設定として扱ってください。アプリケーションが対象のホストパスを事前に承認していない限り、モデル出力やその他の信頼できないペイロードから許可設定を読み込まないでください。
スナップショットと `persist_workspace()` に含まれるのは、引き続きワークスペースルートのみです。追加で許可されたパスはランタイムアクセスであり、永続的なワークスペース状態ではありません。
### 権限
`Permissions` は、マニフェストエントリのファイルシステム権限を制御します。対象となるのはサンドボックスがマテリアライズするファイルであり、モデルの権限、承認ポリシー、API 認証情報ではありません。
デフォルトでは、マニフェストエントリは所有者が読み取り、書き込み、実行可能であり、グループおよびその他のユーザーは読み取り、実行可能です。ステージングされたファイルを非公開、読み取り専用、または実行可能にする必要がある場合は、これをオーバーライドします。
```python
from agents.sandbox import FileMode, Permissions
from agents.sandbox.entries import File
private_notes = File(
content=b"internal notes",
permissions=Permissions(
owner=FileMode.READ | FileMode.WRITE,
group=FileMode.NONE,
other=FileMode.NONE,
),
)
```
`Permissions` は、所有者、グループ、その他のユーザーごとに個別のビットを保存し、さらにエントリがディレクトリかどうかも保持します。直接構築するか、`Permissions.from_str(...)` でモード文字列から解析するか、`Permissions.from_mode(...)` で OS モードから生成できます。
ユーザーは、サンドボックス内で作業を実行できる ID です。その ID をサンドボックス内に存在させる場合は `User` をマニフェストに追加し、シェルコマンド、ファイル読み取り、パッチなどのモデル向けサンドボックスツールをそのユーザーとして実行する場合は、`SandboxAgent.run_as` を設定します。`run_as` がマニフェストにまだ存在しないユーザーを指している場合、ランナーがそのユーザーを有効なマニフェストに自動的に追加します。
```python
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import FileMode, Manifest, Permissions, SandboxAgent, SandboxRunConfig, User
from agents.sandbox.entries import Dir, LocalDir
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
analyst = User(name="analyst")
agent = SandboxAgent(
name="Dataroom analyst",
instructions="Review the files in `dataroom/` and write findings to `output/`.",
default_manifest=Manifest(
# Declare the sandbox user so manifest entries can grant access to it.
users=[analyst],
entries={
"dataroom": LocalDir(
src="./dataroom",
# Let the analyst traverse and read the mounted dataroom, but not edit it.
group=analyst,
permissions=Permissions(
owner=FileMode.READ | FileMode.EXEC,
group=FileMode.READ | FileMode.EXEC,
other=FileMode.NONE,
),
),
"output": Dir(
# Give the analyst a writable scratch/output directory for artifacts.
group=analyst,
permissions=Permissions(
owner=FileMode.ALL,
group=FileMode.ALL,
other=FileMode.NONE,
),
),
},
),
# Run model-facing sandbox actions as this user, so those permissions apply.
run_as=analyst,
)
result = await Runner.run(
agent,
"Summarize the contracts and call out renewal dates.",
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()),
),
)
```
ファイル単位の共有ルールも必要な場合は、ユーザーをマニフェストのグループおよびエントリの `group` メタデータと組み合わせます。`run_as` のユーザーはサンドボックスネイティブの操作を誰が実行するかを制御し、`Permissions` はサンドボックスがワークスペースをマテリアライズした後、そのユーザーがどのファイルを読み取り、書き込み、実行できるかを制御します。
### SnapshotSpec
`SnapshotSpec` は、新しいサンドボックスセッションが保存済みワークスペース内容を復元する場所、および内容を再び永続化する場所を指定します。これはサンドボックスワークスペースのスナップショットポリシーであり、`session_state` は特定のサンドボックスバックエンドを再開するためにシリアライズされた接続状態です。
ローカルの永続スナップショットには `LocalSnapshotSpec` を使用し、アプリがリモートスナップショットクライアントを提供する場合は `RemoteSnapshotSpec` を使用します。ローカルスナップショットを設定できない場合は、フォールバックとして何もしないスナップショットが使用されます。高度な呼び出し元は、ワークスペーススナップショットの永続化が不要な場合に、これを明示的に使用できます。
```python
from pathlib import Path
from agents.run import RunConfig
from agents.sandbox import LocalSnapshotSpec, SandboxRunConfig
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
run_config = RunConfig(
sandbox=SandboxRunConfig(
client=UnixLocalSandboxClient(),
snapshot=LocalSnapshotSpec(base_path=Path("/tmp/my-sandbox-snapshots")),
)
)
```
ランナーが新しいサンドボックスセッションを作成すると、サンドボックスクライアントはそのセッション用のスナップショットインスタンスを構築します。開始時にスナップショットが復元可能であれば、実行を続行する前にサンドボックスが保存済みワークスペース内容を復元します。クリーンアップ時には、ランナー所有のサンドボックスセッションがワークスペースをアーカイブし、スナップショットを通じて再び永続化します。
`snapshot` を省略すると、ランタイムは可能な場合にデフォルトのローカルスナップショット保存先を使用しようとします。設定できない場合は、何もしないスナップショットへフォールバックします。マウントされたパスと一時パスは、永続的なワークスペース内容としてスナップショットにコピーされません。
### サンドボックスのライフサイクル
ライフサイクルには、**SDK 所有**と**開発者所有**の 2 つのモードがあります。
<div class="sandbox-lifecycle-diagram" markdown="1">
```mermaid
sequenceDiagram
participant App
participant Runner
participant Client
participant Sandbox
App->>Runner: Runner.run(..., SandboxRunConfig(client=...))
Runner->>Client: create or resume sandbox
Client-->>Runner: sandbox session
Runner->>Sandbox: start, run tools
Runner->>Sandbox: stop and persist snapshot
Runner->>Client: delete runner-owned resources
App->>Client: create(...)
Client-->>App: sandbox session
App->>Sandbox: async with sandbox
App->>Runner: Runner.run(..., SandboxRunConfig(session=sandbox))
Runner->>Sandbox: run tools
App->>Sandbox: cleanup on context exit / aclose()
```
</div>
サンドボックスが 1 回の実行中のみ存在すればよい場合は、SDK 所有のライフサイクルを使用します。`client`、任意の `manifest`、任意の `snapshot`、クライアントの `options` を渡します。ランナーがサンドボックスを作成または再開して起動し、エージェントを実行し、スナップショット対応のワークスペース状態を永続化し、サンドボックスを停止して、ランナー所有リソースをクライアントにクリーンアップさせます。
```python
result = await Runner.run(
agent,
"Inspect the workspace and summarize what changed.",
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()),
),
)
```
サンドボックスを事前に作成する場合、稼働中の 1 つのサンドボックスを複数回の実行で再利用する場合、実行後にファイルを確認する場合、自分で作成したサンドボックスでストリーミングする場合、またはクリーンアップのタイミングを厳密に決定する場合は、開発者所有のライフサイクルを使用します。`session=...` を渡すと、ランナーはその稼働中のサンドボックスを使用しますが、自動的には閉じません。
```python
sandbox = await client.create(manifest=agent.default_manifest)
async with sandbox:
run_config = RunConfig(sandbox=SandboxRunConfig(session=sandbox))
await Runner.run(agent, "Analyze the files.", run_config=run_config)
await Runner.run(agent, "Write the final report.", run_config=run_config)
```
通常はコンテキストマネージャーを使用します。開始時にサンドボックスを起動し、終了時にセッションのクリーンアップライフサイクルを実行します。アプリでコンテキストマネージャーを使用できない場合は、ライフサイクルメソッドを直接呼び出します。
```python
sandbox = await client.create(
manifest=agent.default_manifest,
snapshot=LocalSnapshotSpec(base_path=Path("/tmp/my-sandbox-snapshots")),
)
try:
await sandbox.start()
await Runner.run(
agent,
"Analyze the files.",
run_config=RunConfig(sandbox=SandboxRunConfig(session=sandbox)),
)
# Persist a checkpoint of the live workspace before doing more work.
# `aclose()` also calls `stop()`, so this is only needed for an explicit mid-lifecycle save.
await sandbox.stop()
finally:
await sandbox.aclose()
```
`stop()` はスナップショット対応のワークスペース内容を永続化するだけで、サンドボックスを破棄しません。`aclose()` は完全なセッションクリーンアップ処理です。停止前フックを実行し、`stop()` を呼び出し、サンドボックスリソースを停止して、セッション単位の依存関係を閉じます。
## `SandboxRunConfig` のオプション
[`SandboxRunConfig`][agents.run_config.SandboxRunConfig] は、サンドボックスセッションの取得元と、新しいセッションの初期化方法を決定する実行ごとのオプションを保持します。
### サンドボックスの取得元
次のオプションは、ランナーがサンドボックスセッションを再利用、再開、作成のいずれで取得するかを決定します。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| オプション | 使用する状況 | 注記 |
| --- | --- | --- |
| `client` | ランナーにサンドボックスセッションの作成、再開、クリーンアップを任せる場合。 | 稼働中のサンドボックス `session` を指定しない限り必須です。 |
| `session` | 稼働中のサンドボックスセッションを既に自分で作成している場合。 | 呼び出し元がライフサイクルを所有し、ランナーはその稼働中のサンドボックスセッションを再利用します。 |
| `session_state` | シリアライズされたサンドボックスセッション状態はあるものの、稼働中のサンドボックスセッションオブジェクトがない場合。 | `client` が必要です。ランナーは、その明示的な状態から所有セッションとして再開します。 |
</div>
実際には、ランナーは次の順序でサンドボックスセッションを解決します。
1. `run_config.sandbox.session` を注入した場合、その稼働中のサンドボックスセッションを直接再利用します。
2. それ以外で、実行を `RunState` から再開する場合は、保存済みのサンドボックスセッション状態を再開します。
3. それ以外で、`run_config.sandbox.session_state` を渡した場合は、その明示的にシリアライズされたサンドボックスセッション状態から再開します。
4. それ以外の場合、ランナーは新しいサンドボックスセッションを作成します。その新しいセッションでは、`run_config.sandbox.manifest` が指定されていればそれを使用し、指定されていなければ `agent.default_manifest` を使用します。
### 新規セッションの入力
次のオプションは、ランナーが新しいサンドボックスセッションを作成する場合にのみ適用されます。
<div class="sandbox-nowrap-first-column-table" markdown="1">
| オプション | 使用する状況 | 注記 |
| --- | --- | --- |
| `manifest` | 新規セッションのワークスペースを一時的にオーバーライドする場合。 | 省略時は `agent.default_manifest` にフォールバックします。 |
| `snapshot` | 新しいサンドボックスセッションをスナップショットから初期化する場合。 | 再開に似たフローやリモートスナップショットクライアントに役立ちます。 |
| `options` | サンドボックスクライアントが作成時オプションを必要とする場合。 | Docker イメージ、Modal アプリ名、E2B テンプレート、タイムアウト、同様のクライアント固有設定でよく使用します。 |
</div>
### マテリアライズの制御
`concurrency_limits` は、サンドボックスのマテリアライズ処理を並列実行できる量を制御します。大規模なマニフェストやローカルディレクトリのコピーで、より厳密なリソース制御が必要な場合は、`SandboxConcurrencyLimits(manifest_entries=..., local_dir_files=...)` を使用します。いずれかの値を `None` に設定すると、その制限のみが無効になります。
`archive_limits` は、アーカイブ展開に対する SDK 側のリソースチェックを制御します。SDK のデフォルトしきい値を有効にするには `archive_limits=SandboxArchiveLimits()` を設定します。アーカイブに対してより厳密なリソース制御が必要な場合は、`SandboxArchiveLimits(max_input_bytes=..., max_extracted_bytes=..., max_members=...)` などの明示的な値を渡します。SDK のアーカイブリソース制限がないデフォルト動作を維持するには `archive_limits=None` のままにし、特定の制限だけを無効にするには個別のフィールドを `None` に設定します。
次の点に注意してください。
- 新規セッション: `manifest=``snapshot=` は、ランナーが新しいサンドボックスセッションを作成する場合にのみ適用されます。
- 再開とスナップショット: `session_state=` は以前にシリアライズされたサンドボックス状態へ再接続しますが、`snapshot=` は保存済みワークスペース内容から新しいサンドボックスセッションを初期化します。
- クライアント固有オプション: `options=` はサンドボックスクライアントによって異なります。Docker および多くのホステッドクライアントでは必須です。
- 注入された稼働中セッション: 実行中のサンドボックス `session` を渡した場合、機能によるマニフェスト更新で、互換性のあるマウント以外のエントリを追加できます。ただし、`manifest.root``manifest.environment``manifest.users``manifest.groups` の変更、既存エントリの削除、エントリ型の置き換え、マウントエントリの追加または変更はできません。
- ランナー API: `SandboxAgent` の実行でも、通常の `Runner.run()``Runner.run_sync()``Runner.run_streamed()` API を使用します。
## 完全なコード例: コーディングタスク
次のコーディング形式のコード例は、デフォルトの出発点として適しています。
```python
import asyncio
from pathlib import Path
from agents import ModelSettings, Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.capabilities import (
Capabilities,
LocalDirLazySkillSource,
Skills,
)
from agents.sandbox.entries import LocalDir
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
EXAMPLE_DIR = Path(__file__).resolve().parent
HOST_REPO_DIR = EXAMPLE_DIR / "repo"
HOST_SKILLS_DIR = EXAMPLE_DIR / "skills"
TARGET_TEST_CMD = "sh tests/test_credit_note.sh"
def build_agent(model: str) -> SandboxAgent[None]:
return SandboxAgent(
name="Sandbox engineer",
model=model,
instructions=(
"Inspect the repo, make the smallest correct change, run the most relevant checks, "
"and summarize the file changes and risks. "
"Read `repo/task.md` before editing files. Stay grounded in the repository, preserve "
"existing behavior, and mention the exact verification command you ran. "
"Use the `$credit-note-fixer` skill before editing files. If the repo lives under "
"`repo/`, remember that `apply_patch` paths stay relative to the sandbox workspace "
"root, so edits still target `repo/...`."
),
# Put repos and task files in the manifest.
default_manifest=Manifest(
entries={
"repo": LocalDir(src=HOST_REPO_DIR),
}
),
capabilities=Capabilities.default() + [
Skills(
lazy_from=LocalDirLazySkillSource(
# This is a host path read by the SDK process.
# Requested skills are copied into `skills_path` in the sandbox.
source=LocalDir(src=HOST_SKILLS_DIR),
)
),
],
model_settings=ModelSettings(tool_choice="required"),
)
async def main(model: str, prompt: str) -> None:
result = await Runner.run(
build_agent(model),
prompt,
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()),
workflow_name="Sandbox coding example",
),
)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(
main(
model="gpt-5.6-sol",
prompt=(
"Open `repo/task.md`, use the `$credit-note-fixer` skill, fix the bug, "
f"run `{TARGET_TEST_CMD}`, and summarize the change."
),
)
)
```
[examples/sandbox/docs/coding_task.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docs/coding_task.py)を参照してください。このコード例では、Unix ローカル実行で決定論的に検証できるように、小規模なシェルベースのリポジトリを使用しています。実際のタスクリポジトリでは、もちろん Python、JavaScript、その他の任意の言語を使用できます。
## 一般的なパターン
上記の完全なコード例から始めてください。多くの場合、同じ `SandboxAgent` をそのまま維持し、サンドボックスクライアント、サンドボックスセッションの取得元、またはワークスペースの取得元のみを変更できます。
### サンドボックスクライアントの切り替え
エージェント定義は同じまま維持し、実行設定のみを変更します。コンテナ分離やイメージの同等性が必要な場合は Docker を使用し、プロバイダー管理の実行が必要な場合はホステッドプロバイダーを使用します。コード例とプロバイダーオプションについては、[サンドボックスクライアント](clients.md)を参照してください。
### ワークスペースのオーバーライド
エージェント定義は同じまま維持し、新規セッション用マニフェストのみを差し替えます。
```python
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxRunConfig
from agents.sandbox.entries import GitRepo
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
run_config = RunConfig(
sandbox=SandboxRunConfig(
client=UnixLocalSandboxClient(),
manifest=Manifest(
entries={
"repo": GitRepo(repo="openai/openai-agents-python", ref="main"),
}
),
),
)
```
エージェントを再構築せずに、同じエージェントロールを異なるリポジトリ、資料、タスクバンドルに対して実行する場合に使用します。上記の検証済みコーディングコード例では、一時的なオーバーライドではなく `default_manifest` を使用して同じパターンを示しています。
### サンドボックスセッションの注入
ライフサイクルの明示的な制御、実行後の確認、出力のコピーが必要な場合は、稼働中のサンドボックスセッションを注入します。
```python
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import SandboxRunConfig
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
client = UnixLocalSandboxClient()
sandbox = await client.create(manifest=agent.default_manifest)
async with sandbox:
result = await Runner.run(
agent,
prompt,
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
),
)
```
実行後にワークスペースを確認する場合、または起動済みのサンドボックスセッションでストリーミングする場合に使用します。[examples/sandbox/docs/coding_task.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docs/coding_task.py)および[examples/sandbox/docker/docker_runner.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docker/docker_runner.py)を参照してください。
### セッション状態からの再開
`RunState` の外部でサンドボックス状態を既にシリアライズしている場合は、ランナーにその状態から再接続させます。
```python
from agents.run import RunConfig
from agents.sandbox import SandboxRunConfig
serialized = load_saved_payload()
restored_state = client.deserialize_session_state(serialized)
run_config = RunConfig(
sandbox=SandboxRunConfig(
client=client,
session_state=restored_state,
),
)
```
サンドボックス状態を独自のストレージやジョブシステムに保存し、`Runner` でその状態から直接再開する場合に使用します。シリアライズとデシリアライズのフローについては、[examples/sandbox/extensions/blaxel_runner.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/extensions/blaxel_runner.py)を参照してください。
### スナップショットからの開始
保存済みのファイルや成果物から新しいサンドボックスを初期化します。
```python
from pathlib import Path
from agents.run import RunConfig
from agents.sandbox import LocalSnapshotSpec, SandboxRunConfig
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
run_config = RunConfig(
sandbox=SandboxRunConfig(
client=UnixLocalSandboxClient(),
snapshot=LocalSnapshotSpec(base_path=Path("/tmp/my-sandbox-snapshot")),
),
)
```
新しい実行を `agent.default_manifest` だけでなく、保存済みワークスペース内容から開始する場合に使用します。ローカルスナップショットのフローについては [examples/sandbox/memory.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory.py)、リモートスナップショットクライアントについては [examples/sandbox/sandbox_agent_with_remote_snapshot.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agent_with_remote_snapshot.py)を参照してください。
### Git からのスキル読み込み
ローカルスキルソースを、リポジトリを使用するソースに置き換えます。
```python
from agents.sandbox.capabilities import Capabilities, Skills
from agents.sandbox.entries import GitRepo
capabilities = Capabilities.default() + [
Skills(from_=GitRepo(repo="sdcoffey/tax-prep-skills", ref="main")),
]
```
スキルバンドルに独自のリリースサイクルがある場合や、複数のサンドボックス間で共有する場合に使用します。[examples/sandbox/tax_prep.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/tax_prep.py)を参照してください。
### ツールとしての公開
ツールエージェントは、独自のサンドボックス境界を使用するか、親実行の稼働中サンドボックスを再利用できます。再利用は、高速な読み取り専用の探索エージェントに役立ちます。別のサンドボックスを作成、ハイドレート、スナップショット化するコストをかけずに、親が使用しているワークスペースをそのまま確認できます。
```python
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import FileMode, Manifest, Permissions, SandboxAgent, SandboxRunConfig, User
from agents.sandbox.entries import Dir, File
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
coordinator = User(name="coordinator")
explorer = User(name="explorer")
manifest = Manifest(
users=[coordinator, explorer],
entries={
"pricing_packet": Dir(
group=coordinator,
permissions=Permissions(
owner=FileMode.ALL,
group=FileMode.ALL,
other=FileMode.READ | FileMode.EXEC,
directory=True,
),
children={
"pricing.md": File(
content=b"Pricing packet contents...",
group=coordinator,
permissions=Permissions(
owner=FileMode.ALL,
group=FileMode.ALL,
other=FileMode.READ,
),
),
},
),
"work": Dir(
group=coordinator,
permissions=Permissions(
owner=FileMode.ALL,
group=FileMode.ALL,
other=FileMode.NONE,
directory=True,
),
),
},
)
pricing_explorer = SandboxAgent(
name="Pricing Explorer",
instructions="Read `pricing_packet/` and summarize commercial risk. Do not edit files.",
run_as=explorer,
)
client = UnixLocalSandboxClient()
sandbox = await client.create(manifest=manifest)
async with sandbox:
shared_run_config = RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
)
orchestrator = SandboxAgent(
name="Revenue Operations Coordinator",
instructions="Coordinate the review and write final notes to `work/`.",
run_as=coordinator,
tools=[
pricing_explorer.as_tool(
tool_name="review_pricing_packet",
tool_description="Inspect the pricing packet and summarize commercial risk.",
run_config=shared_run_config,
max_turns=2,
),
],
)
result = await Runner.run(
orchestrator,
"Review the pricing packet, then write final notes to `work/summary.md`.",
run_config=shared_run_config,
)
```
ここでは、親エージェントが `coordinator` として実行され、探索用ツールエージェントが同じ稼働中サンドボックスセッション内で `explorer` として実行されます。`pricing_packet/` のエントリは `other` ユーザーが読み取れるため、探索エージェントはすばやく確認できますが、書き込み権限はありません。`work/` ディレクトリはコーディネーターのユーザーまたはグループのみが利用できるため、探索エージェントを読み取り専用に維持しながら、親は最終成果物を書き込めます。
ツールエージェントに実際の分離が必要な場合は、独自のサンドボックス `RunConfig` を指定します。
```python
from docker import from_env as docker_from_env
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig
from agents.sandbox.sandboxes.docker import DockerSandboxClient, DockerSandboxClientOptions
rollout_agent = SandboxAgent(
name="Rollout Reviewer",
instructions="Inspect the rollout packet and summarize implementation risk.",
)
rollout_agent.as_tool(
tool_name="review_rollout_risk",
tool_description="Inspect the rollout packet and summarize implementation risk.",
run_config=RunConfig(
sandbox=SandboxRunConfig(
client=DockerSandboxClient(docker_from_env()),
options=DockerSandboxClientOptions(image="python:3.14-slim"),
),
),
)
```
ツールエージェントが自由に変更を行う場合、信頼できないコマンドを実行する場合、または異なるバックエンドやイメージを使用する場合は、別のサンドボックスを使用します。[examples/sandbox/sandbox_agents_as_tools.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agents_as_tools.py)を参照してください。
### ローカルツールおよび MCP との組み合わせ
サンドボックスワークスペースを維持しながら、同じエージェントで通常のツールも使用できます。
```python
from agents.sandbox import SandboxAgent
from agents.sandbox.capabilities import Shell
agent = SandboxAgent(
name="Workspace reviewer",
instructions="Inspect the workspace and call host tools when needed.",
tools=[get_discount_approval_path],
mcp_servers=[server],
capabilities=[Shell()],
)
```
ワークスペースの確認がエージェントの作業の一部にすぎない場合に使用します。[examples/sandbox/sandbox_agent_with_tools.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agent_with_tools.py)を参照してください。
## メモリ
後続のサンドボックスエージェント実行で以前の実行から学習する必要がある場合は、`Memory` 機能を使用します。メモリは SDK の会話用 `Session` メモリとは別のものです。学習内容をサンドボックスワークスペース内のファイルに抽出し、後続の実行でそのファイルを読み取れるようにします。
設定、読み取りと生成の動作、複数ターンの会話、レイアウトの分離については、[エージェントメモリ](memory.md)を参照してください。
## 構成パターン
単一エージェントのパターンを理解したら、次の設計上の検討事項は、より大きなシステムのどこにサンドボックス境界を配置するかです。
サンドボックスエージェントは、引き続き SDK の他の要素と組み合わせられます。
- [ハンドオフ](../handoffs.md): ドキュメント量の多い作業を、サンドボックスを使用しない受付エージェントからサンドボックスレビュアーへ引き継ぎます。
- [Agents as tools](../tools.md#agents-as-tools): 複数のサンドボックスエージェントをツールとして公開します。通常は、各 `Agent.as_tool(...)` 呼び出しに `run_config=RunConfig(sandbox=SandboxRunConfig(...))` を渡し、各ツールに独自のサンドボックス境界を割り当てます。
- [MCP](../mcp.md) と通常の関数ツール: サンドボックス機能は、`mcp_servers` および通常の Python ツールと共存できます。
- [エージェントの実行](../running_agents.md): サンドボックス実行でも通常の `Runner` API を使用します。
特に一般的なのは、次の 2 つのパターンです。
- サンドボックスを使用しないエージェントが、ワークスペースの分離を必要とするワークフロー部分だけをサンドボックスエージェントへハンドオフする
- オーケストレーターが複数のサンドボックスエージェントをツールとして公開し、通常は `Agent.as_tool(...)` 呼び出しごとに個別のサンドボックス `RunConfig` を指定して、各ツールに独自の分離ワークスペースを割り当てる
### ターンとサンドボックス実行
ハンドオフと、エージェントをツールとして使用する呼び出しは、分けて説明すると理解しやすくなります。
ハンドオフでは、トップレベルの実行とトップレベルのターンループは引き続き 1 つです。アクティブなエージェントは変わりますが、実行がネストされるわけではありません。サンドボックスを使用しない受付エージェントがサンドボックスレビュアーへハンドオフすると、同じ実行内の次のモデル呼び出しはサンドボックスエージェント用に準備され、そのサンドボックスエージェントが次のターンを担当します。つまり、ハンドオフによって、同じ実行の次のターンを担当するエージェントが変わります。[examples/sandbox/handoffs.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/handoffs.py)を参照してください。
`Agent.as_tool(...)` では関係が異なります。外側のオーケストレーターは、ツールを呼び出すかどうかの決定に外側の 1 ターンを使用し、そのツール呼び出しによってサンドボックスエージェントのネストされた実行が開始されます。ネストされた実行には、独自のターンループ、`max_turns`、承認、通常は独自のサンドボックス `RunConfig` があります。ネストされた 1 ターンで完了する場合も、複数ターンかかる場合もあります。外側のオーケストレーターから見ると、これらの作業はすべて 1 回のツール呼び出しの背後で行われるため、ネストされたターンによって外側の実行のターンカウンターが増えることはありません。[examples/sandbox/sandbox_agents_as_tools.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agents_as_tools.py)を参照してください。
承認の動作も同様に分かれます。
- ハンドオフでは、サンドボックスエージェントが同じ実行内のアクティブなエージェントになるため、承認は同じトップレベルの実行に維持されます。
- `Agent.as_tool(...)` では、サンドボックスのツールエージェント内で発生した承認も外側の実行に表示されますが、保存されたネスト済み実行状態から取得され、外側の実行の再開時にネストされたサンドボックス実行を再開します。
## 関連資料
- [クイックスタート](../sandbox_agents.md): サンドボックスエージェントを 1 つ実行します。
- [サンドボックスクライアント](clients.md): ローカル、Docker、ホステッド、マウントのオプションを選択します。
- [エージェントメモリ](memory.md): 以前のサンドボックス実行から得た学習内容を保存し、再利用します。
- [examples/sandbox/](https://github.com/openai/openai-agents-python/tree/main/examples/sandbox): 実行可能なローカル、コーディング、メモリ、ハンドオフ、エージェント構成のパターン。
+189
View File
@@ -0,0 +1,189 @@
---
search:
exclude: true
---
# エージェントメモリ
メモリにより、今後の sandbox エージェントの実行は過去の実行から学習できます。これは、メッセージ履歴を保存する SDK の会話用 [`Session`](../sessions/index.md) メモリとは別のものです。メモリは、過去の実行から得た学びを sandbox ワークスペース内のファイルに要約します。
!!! warning "ベータ機能"
Sandbox エージェントはベータ版です。一般提供までに API の詳細、デフォルト値、サポートされる機能が変更される可能性があり、時間とともにさらに高度な機能が追加されることも想定してください。
メモリは、今後の実行における 3 種類のコストを削減できます。
1. エージェントのコスト: エージェントがワークフローの完了に長い時間を要した場合、次回の実行では探索が少なくて済むはずです。これにより、トークン使用量と完了までの時間を削減できます。
2. ユーザーのコスト: ユーザーがエージェントを修正したり好みを表明したりした場合、今後の実行でそのフィードバックを記憶できます。これにより、人による介入を削減できます。
3. コンテキストのコスト: エージェントが以前にタスクを完了していて、ユーザーがそのタスクを発展させたい場合、ユーザーは以前のスレッドを探したり、すべてのコンテキストを再入力したりする必要がないはずです。これにより、タスク説明を短くできます。
バグを修正し、メモリを生成し、スナップショットを再開し、そのメモリを後続の検証実行で使用する、2 回の実行からなる完全なコード例については、[examples/sandbox/memory.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory.py) を参照してください。独立したメモリレイアウトを持つマルチターン、マルチエージェントのコード例については、[examples/sandbox/memory_multi_agent_multiturn.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory_multi_agent_multiturn.py) を参照してください。
## メモリの有効化
sandbox エージェントに機能として `Memory()` を追加します。
```python
from pathlib import Path
import tempfile
from agents.sandbox import LocalSnapshotSpec, SandboxAgent
from agents.sandbox.capabilities import Filesystem, Memory, Shell
agent = SandboxAgent(
name="Memory-enabled reviewer",
instructions="Inspect the workspace and preserve useful lessons for follow-up runs.",
capabilities=[Memory(), Filesystem(), Shell()],
)
with tempfile.TemporaryDirectory(prefix="sandbox-memory-example-") as snapshot_dir:
sandbox = await client.create(
manifest=manifest,
snapshot=LocalSnapshotSpec(base_path=Path(snapshot_dir)),
)
```
読み取りが有効な場合、`Memory()` には `Shell()` が必要です。これにより、挿入されたサマリーだけでは不十分なときに、エージェントがメモリファイルを読み取り、検索できます。ライブメモリ更新が有効な場合(デフォルト)、`Filesystem()` も必要です。これにより、エージェントが古くなったメモリを発見した場合や、ユーザーがメモリの更新を依頼した場合に、`memories/MEMORY.md` を更新できます。
デフォルトでは、メモリアーティファクトは sandbox ワークスペースの `memories/` 配下に保存されます。後の実行で再利用するには、同じライブ sandbox セッションを維持するか、永続化されたセッション状態またはスナップショットから再開することで、設定済みのメモリディレクトリ全体を保持して再利用してください。新しい空の sandbox は空のメモリで開始されます。
`Memory()` は、メモリの読み取りと生成の両方を有効にします。メモリを読み取るが新しいメモリは生成すべきでないエージェントには、`Memory(generate=None)` を使用します。たとえば、内部エージェント、サブエージェント、チェッカー、または実行から得られるシグナルが多くない 1 回限りのツールエージェントです。後で使うメモリを生成する必要はあるものの、ユーザーが既存メモリによる影響を望まない場合は、`Memory(read=None)` を使用します。
## メモリの読み取り
メモリ読み取りでは段階的開示を使用します。実行の開始時に、SDK は一般的に役立つヒント、ユーザーの好み、利用可能なメモリの小さなサマリー(`memory_summary.md`)を、エージェントの developer プロンプトに挿入します。これにより、エージェントは過去の作業が関連しそうかどうかを判断するのに十分なコンテキストを得られます。
過去の作業が関連しそうな場合、エージェントは現在のタスクからキーワードを抽出して、設定されたメモリインデックス(`memories_dir` 配下の `MEMORY.md`)を検索します。より詳細が必要な場合にのみ、設定された `rollout_summaries/` ディレクトリ配下にある対応する過去のロールアウトサマリーを開きます。
メモリは古くなることがあります。エージェントには、メモリをガイダンスとしてのみ扱い、現在の環境を信頼するよう指示されています。デフォルトでは、メモリ読み取りでは `live_update` が有効です。そのため、エージェントが古くなったメモリを発見した場合、同じ実行内で設定済みの `MEMORY.md` を更新できます。実行中にメモリを読み取るが変更してほしくない場合、たとえばレイテンシに敏感な実行では、ライブ更新を無効にしてください。
## メモリの生成
実行が完了すると、sandbox ランタイムはその実行セグメントを会話ファイルに追記します。蓄積された会話ファイルは、sandbox セッションが閉じられるときに処理されます。
メモリ生成には 2 つのフェーズがあります。
1. フェーズ 1: 会話の抽出。メモリ生成モデルが、蓄積された 1 つの会話ファイルを処理し、会話サマリーを生成します。system、developer、reasoning のコンテンツは省略されます。会話が長すぎる場合は、先頭と末尾を保持したうえで、コンテキストウィンドウに収まるよう切り詰められます。また、未加工のメモリ抽出も生成します。これは、フェーズ 2 が統合できる会話からの簡潔なメモです。
2. フェーズ 2: レイアウトの統合。統合エージェントは、1 つのメモリレイアウトに対応する未加工のメモリを読み取り、より多くの根拠が必要な場合は会話サマリーを開き、パターンを `MEMORY.md``memory_summary.md` に抽出します。
デフォルトのワークスペースレイアウトは次のとおりです。
```text
workspace/
├── sessions/
│ └── <rollout-id>.jsonl
└── memories/
├── memory_summary.md
├── MEMORY.md
├── raw_memories.md (intermediate)
├── phase_two_selection.json (intermediate)
├── raw_memories/ (intermediate)
│ └── <rollout-id>.md
├── rollout_summaries/
│ └── <rollout-id>_<slug>.md
└── skills/
```
`MemoryGenerateConfig` でメモリ生成を設定できます。
```python
from agents.sandbox import MemoryGenerateConfig
from agents.sandbox.capabilities import Memory
memory = Memory(
generate=MemoryGenerateConfig(
max_raw_memories_for_consolidation=128,
extra_prompt="Pay extra attention to what made the customer more satisfied or annoyed",
),
)
```
`extra_prompt` を使用して、GTM エージェント向けの顧客や会社の詳細など、ユースケースで最も重要なシグナルをメモリ生成器に伝えます。
最近の未加工メモリが `max_raw_memories_for_consolidation`(デフォルトは 256)を超える場合、フェーズ 2 は最新の会話のメモリだけを保持し、古いものを削除します。新しさは、会話が最後に更新された時刻に基づきます。この忘却メカニズムにより、メモリが最新の環境を反映しやすくなります。
## マルチターン会話
マルチターンの sandbox チャットでは、同じライブ sandbox セッションとともに通常の SDK `Session` を使用します。
```python
from agents import Runner, SQLiteSession
from agents.run import RunConfig
from agents.sandbox import SandboxRunConfig
conversation_session = SQLiteSession("gtm-q2-pipeline-review")
sandbox = await client.create(manifest=agent.default_manifest)
async with sandbox:
run_config = RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
workflow_name="GTM memory example",
)
await Runner.run(
agent,
"Analyze data/leads.csv and identify one promising GTM segment.",
session=conversation_session,
run_config=run_config,
)
await Runner.run(
agent,
"Using that analysis, write a short outreach hypothesis.",
session=conversation_session,
run_config=run_config,
)
```
どちらの実行も、同じ SDK 会話セッション(`session=conversation_session`)を渡すため、1 つのメモリ会話ファイルに追記され、したがって同じ `session.session_id` を共有します。これはライブワークスペースを識別する sandbox(`sandbox`)とは異なります。`sandbox` はメモリ会話 ID としては使用されません。sandbox セッションが閉じられると、フェーズ 1 は蓄積された会話を参照するため、2 つの孤立したターンではなく、やり取り全体からメモリを抽出できます。
複数の `Runner.run(...)` 呼び出しを 1 つのメモリ会話にしたい場合は、それらの呼び出し全体で安定した識別子を渡してください。メモリが実行を会話に関連付けるときは、次の順序で解決します。
1. `conversation_id``Runner.run(...)` に渡した場合)
2. `session.session_id``SQLiteSession` などの SDK `Session` を渡した場合)
3. `RunConfig.group_id`(上記のどちらも存在しない場合)
4. 生成された実行ごとの ID(安定した識別子が存在しない場合)
## エージェントごとのメモリ分離における異なるレイアウトの利用
メモリの分離はエージェント名ではなく `MemoryLayoutConfig` に基づきます。同じレイアウトと同じメモリ会話 ID を持つエージェントは、1 つのメモリ会話と 1 つの統合済みメモリを共有します。異なるレイアウトを持つエージェントは、同じ sandbox ワークスペースを共有している場合でも、別々のロールアウトファイル、未加工メモリ、`MEMORY.md``memory_summary.md` を保持します。
複数のエージェントが 1 つの sandbox を共有するものの、メモリは共有すべきでない場合は、別々のレイアウトを使用します。
```python
from agents import SQLiteSession
from agents.sandbox import MemoryLayoutConfig, SandboxAgent
from agents.sandbox.capabilities import Filesystem, Memory, Shell
gtm_agent = SandboxAgent(
name="GTM reviewer",
instructions="Analyze GTM workspace data and write concise recommendations.",
capabilities=[
Memory(
layout=MemoryLayoutConfig(
memories_dir="memories/gtm",
sessions_dir="sessions/gtm",
)
),
Filesystem(),
Shell(),
],
)
engineering_agent = SandboxAgent(
name="Engineering reviewer",
instructions="Inspect engineering workspaces and summarize fixes and risks.",
capabilities=[
Memory(
layout=MemoryLayoutConfig(
memories_dir="memories/engineering",
sessions_dir="sessions/engineering",
)
),
Filesystem(),
Shell(),
],
)
gtm_session = SQLiteSession("gtm-q2-pipeline-review")
engineering_session = SQLiteSession("eng-invoice-test-fix")
```
これにより、GTM 分析がエンジニアリングのバグ修正メモリに統合されたり、その逆が起きたりすることを防げます。
+117
View File
@@ -0,0 +1,117 @@
---
search:
exclude: true
---
# クイックスタート
!!! warning "ベータ機能"
サンドボックスエージェントはベータ版です。一般提供までに API の詳細、デフォルト、サポートされる機能が変更される可能性があります。また、今後さらに高度な機能が追加される予定です。
最新のエージェントは、ファイルシステム上の実ファイルを操作できるときに最大限の力を発揮します。Agents SDK の **サンドボックスエージェント** は、大規模なドキュメント群の検索、ファイルの編集、コマンドの実行、成果物の生成、保存済みのサンドボックス状態からの作業再開が可能な永続ワークスペースをモデルに提供します。
SDK は、ファイルのステージング、ファイルシステムツール、シェルアクセス、サンドボックスのライフサイクル、スナップショット、プロバイダー固有の連携コードを自分で組み合わせることなく、この実行基盤を提供します。通常の `Agent``Runner` のフローを維持しながら、ワークスペース用の `Manifest`、サンドボックスネイティブツール用の機能、作業の実行場所を指定する `SandboxRunConfig` を追加できます。
## 前提条件
- Python 3.10 以降
- OpenAI Agents SDK に関する基本的な知識
- サンドボックスクライアント。ローカル開発では、まず `UnixLocalSandboxClient` を使用してください。
## インストール
SDK をまだインストールしていない場合は、次を実行します。
```bash
pip install openai-agents
```
Docker ベースのサンドボックスの場合は、次を実行します。
```bash
pip install "openai-agents[docker]"
```
## ローカルサンドボックスエージェントの作成
この例では、ローカルリポジトリを `repo/` 配下にステージングし、ローカルスキルを遅延読み込みして、実行時にランナーが Unix ローカルのサンドボックスセッションを作成できるようにします。
```python
import asyncio
from pathlib import Path
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.capabilities import Capabilities, LocalDirLazySkillSource, Skills
from agents.sandbox.entries import LocalDir
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
EXAMPLE_DIR = Path(__file__).resolve().parent
HOST_REPO_DIR = EXAMPLE_DIR / "repo"
HOST_SKILLS_DIR = EXAMPLE_DIR / "skills"
def build_agent(model: str) -> SandboxAgent[None]:
return SandboxAgent(
name="Sandbox engineer",
model=model,
instructions=(
"Read `repo/task.md` before editing files. Stay grounded in the repository, preserve "
"existing behavior, and mention the exact verification command you ran. "
"If you edit files with apply_patch, paths are relative to the sandbox workspace root."
),
default_manifest=Manifest(
entries={
"repo": LocalDir(src=HOST_REPO_DIR),
}
),
capabilities=Capabilities.default() + [
Skills(
lazy_from=LocalDirLazySkillSource(
# This is a host path read by the SDK process.
# Requested skills are copied into `skills_path` in the sandbox.
source=LocalDir(src=HOST_SKILLS_DIR),
)
),
],
)
async def main() -> None:
result = await Runner.run(
build_agent("gpt-5.6-sol"),
"Open `repo/task.md`, fix the issue, run the targeted test, and summarize the change.",
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()),
workflow_name="Sandbox coding example",
),
)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
```
[examples/sandbox/docs/coding_task.py](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docs/coding_task.py) を参照してください。この例では、Unix ローカルでの実行間で決定論的に検証できるように、シェルベースの小規模なリポジトリを使用しています。
## 主な選択肢
基本的な実行が動作した後、多くの場合、次の選択肢を検討します。
- `default_manifest`: 新規サンドボックスセッション向けのファイル、リポジトリ、ディレクトリ、マウント
- `instructions`: 複数のプロンプトにわたって適用する短いワークフロールール
- `base_instructions`: SDK のサンドボックスプロンプトを置き換えるための高度な回避手段
- `capabilities`: ファイルシステムの編集/画像検査、シェル、スキル、メモリ、コンパクションなどのサンドボックスネイティブツール
- `run_as`: モデル向けツールで使用するサンドボックスのユーザー ID
- `SandboxRunConfig.client`: サンドボックスのバックエンド
- `SandboxRunConfig.session``session_state`、または `snapshot`: 後続の実行を以前の作業へ再接続する方法
## 次のステップ
- [概念](sandbox/guide.md): マニフェスト、機能、権限、スナップショット、実行設定、構成パターンについて理解します。
- [サンドボックスクライアント](sandbox/clients.md): Unix ローカル、Docker、ホステッドプロバイダー、マウント戦略を選択します。
- [エージェントメモリ](sandbox/memory.md): 過去のサンドボックス実行から得た知見を保持し、再利用します。
シェルアクセスを一時的なツールとしてのみ使用する場合は、[ツールガイド](tools.md)のホステッドシェルから始めてください。ワークスペースの分離、サンドボックスクライアントの選択、またはサンドボックスセッションの再開動作が設計に含まれる場合は、サンドボックスエージェントを使用してください。
+21 -21
View File
@@ -4,15 +4,15 @@ search:
---
# 高度な SQLite セッション
`AdvancedSQLiteSession`基本的な `SQLiteSession` の拡張版であり、会話の分岐、詳細な使用状況分析、構造化された会話クエリなど高度な会話管理機能を提供します。
`AdvancedSQLiteSession` は基本的な `SQLiteSession` の拡張版であり、会話の分岐、詳細な使用状況分析、構造化された会話クエリなど高度な会話管理機能を提供します。
## 機能
- **会話の分岐**: 任意のユーザーメッセージから代替の会話パスを作成
- **使用状況トラッキング**: ターンごとの詳細なトークン使用状況分析完全な JSON 内訳付き
- **構造化クエリ**: ターン単位の会話、ツール使用統計などを取得
- **ブランチ管理**: 独立したブランチ切り替えと管理
- **メッセージ構造メタデータ**: メッセージタイプ、ツール使用状況、会話フローを追跡
- **会話の分岐**: 任意のユーザーメッセージからの会話パスを作成します
- **使用状況の追跡**: ターンごとの詳細なトークン使用状況分析を、完全な JSON 内訳付きで提供します
- **構造化クエリ**: ターンの会話、ツール使用状況の統計などを取得します
- **ブランチ管理**: 独立したブランチ切り替えと管理を行います
- **メッセージ構造メタデータ**: メッセージタイプ、ツール使用、会話フローを追跡します
## クイックスタート
@@ -84,16 +84,16 @@ session = AdvancedSQLiteSession(
### パラメーター
- `session_id` (str): 会話セッションの一意識別子
- `db_path` (str | Path): SQLite データベースファイルへのパス。デフォルトはメモリストレージ用の `:memory:`
- `create_tables` (bool): 高度なテーブルを自動作成するかどうか。デフォルトは `False`
- `logger` (logging.Logger | None): セッション用のカスタムロガー。デフォルトはモジュールロガー
- `session_id` (str): 会話セッションの一意識別子
- `db_path` (str | Path): SQLite データベースファイルへのパス。デフォルトはインメモリストレージ用の `:memory:` です
- `create_tables` (bool): 高度なテーブルを自動的に作成するかどうか。デフォルトは `False` です
- `logger` (logging.Logger | None): セッション用のカスタムロガー。デフォルトはモジュールロガーです
## 使用状況トラッキング
## 使用状況の追跡
AdvancedSQLiteSession は、会話ターンごとトークン使用データを保存することで、詳細な使用状況分析を提供します。**これは各エージェント実行後に `store_run_usage` メソッドが呼び出されることに完全に依存します。**
AdvancedSQLiteSession は、会話ターンごとトークン使用状況データを保存することで、詳細な使用状況分析を提供します。 **これは各エージェント実行後に `store_run_usage` メソッドが呼び出されることに完全に依存します。**
### 使用データの保存
### 使用状況データの保存
```python
# After each agent run, store the usage data
@@ -107,7 +107,7 @@ await session.store_run_usage(result)
# - Detailed JSON token information (if available)
```
### 使用統計の取得
### 使用状況統計の取得
```python
# Get session-level usage (all branches)
@@ -137,7 +137,7 @@ turn_2_usage = await session.get_turn_usage(user_turn_number=2)
## 会話の分岐
AdvancedSQLiteSession の主要機能の 1 つは、任意のユーザーメッセージから会話ブランチを作成できることです。これにより、代替の会話パスを探索できす。
AdvancedSQLiteSession の主要機能の 1 つは、任意のユーザーメッセージから会話ブランチを作成し、別の会話パスを探索できることです。
### ブランチの作成
@@ -245,17 +245,17 @@ for turn in matching_turns:
### メッセージ構造
セッションは、以下を含むメッセージ構造を自動的に追跡します。
セッションは、を含むメッセージ構造を自動的に追跡します。
- メッセージタイプ (user, assistant, tool_call など)
- ツール呼び出しのツール名
- メッセージタイプ(ユーザー、assistanttool_call など
- ツール呼び出しのツール名
- ターン番号とシーケンス番号
- ブランチ関連付け
- ブランチとの関連付け
- タイムスタンプ
## データベーススキーマ
AdvancedSQLiteSession は、基本的な SQLite スキーマを次の 2 つの追加テーブルで拡張します。
AdvancedSQLiteSession は、基本的な SQLite スキーマを 2 つの追加テーブルで拡張します。
### message_structure テーブル
@@ -298,7 +298,7 @@ CREATE TABLE turn_usage (
## 完全な例
すべての機能を包括的に示すデモについては、[完全な例](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py)をご確認ください。
すべての機能を包括的に示す [完全な例](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py) を確認してください。
## API リファレンス
+22 -22
View File
@@ -4,18 +4,18 @@ search:
---
# 暗号化セッション
`EncryptedSession` は、あらゆるセッション実装に対して透過的な暗号化を提供し、古い項目の自動有効期限切れによって会話データを保護します。
`EncryptedSession` は、任意のセッション実装に透過的な暗号化を提供し、古いアイテムの自動期限切れによって会話データを保護します。
## 機能
- **透過的な暗号化**: あらゆるセッションを Fernet 暗号化でラップします
- **セッションごとのキー**: HKDF 導出を使用して、セッションごとに一意の暗号化を行います
- **自動有効期限切れ**: TTL が期限切れになると、古い項目は自動的にスキップされます
- **そのまま置き換え可能**: 既存のあらゆるセッション実装で動作します
- **透過的な暗号化**: 任意のセッションを Fernet 暗号化でラップします
- **セッションごとのキー**: HKDF キー導出を使用して、セッションごとに一意の暗号化を行います
- **自動期限切れ**: TTL が期限切れになると、古いアイテムは取得時に黙ってスキップされます
- **ドロップイン置換**: 既存の任意のセッション実装で動作します
## インストール
暗号化セッションには `encrypt` 追加機能が必要です:
暗号化セッションには `encrypt` extra が必要です
```bash
pip install openai-agents[encrypt]
@@ -57,7 +57,7 @@ if __name__ == "__main__":
### 暗号化キー
暗号化キーには、Fernet キーまたは任意の文字列を使用できます:
暗号化キーには、Fernet キーまたは任意の文字列を指定できます
```python
from agents.extensions.memory import EncryptedSession
@@ -81,7 +81,7 @@ session = EncryptedSession(
### TTL (有効期間)
暗号化された項目を有効とする期間を設定します:
暗号化されたアイテムが有効であり続ける期間を設定します
```python
# Items expire after 1 hour
@@ -101,7 +101,7 @@ session = EncryptedSession(
)
```
## 異なるセッションタイプでの使用
## さまざまなセッションタイプでの使用
### SQLite セッションでの使用
@@ -140,30 +140,30 @@ session = EncryptedSession(
!!! warning "高度なセッション機能"
`AdvancedSQLiteSession` のような高度なセッション実装`EncryptedSession`使用する場合は、次の点に注意してください:
`EncryptedSession``AdvancedSQLiteSession` のような高度なセッション実装使用する場合は、次の点に注意してください
- メッセージ内容暗号化されるため、`find_turns_by_content()` のようなメソッドは効果的に機能しません
- コンテンツベースの検索は暗号化データに対して実行されるため、有効性が制限されます
- メッセージ内容暗号化されるため、`find_turns_by_content()` のようなメソッドは効果的に動作しません
- コンテンツベースの検索は暗号化されたデータに対して実行されるため、有効性が制限されます
## 導出
## キー導出
EncryptedSession は HKDF (HMAC-based Key Derivation Function) を使用して、セッションごとに一意の暗号化キーを導出します:
EncryptedSession は HKDF (HMAC-based Key Derivation Function) を使用して、セッションごとに一意の暗号化キーを導出します
- **マスターキー**: 提供た暗号化キー
- **マスターキー**: 提供された暗号化キー
- **セッションソルト**: セッション ID
- **Info 文字列**: `"agents.session-store.hkdf.v1"`
- **情報文字列**: `"agents.session-store.hkdf.v1"`
- **出力**: 32 バイトの Fernet キー
これにより、次が保証されます:
- 各セッション一意の暗号化キーを持つこと
- マスターキーなしではキーを導出できないこと
- セッションデータを異なるセッション間で復号できないこと
これにより、次のことが保証されます
- 各セッション一意の暗号化キーがあります
- マスターキーがなければキーを導出できません
- セッションデータを異なるセッション間で復号できません
## 自動有効期限切れ
## 自動期限切れ
項目が TTL を超えると、取得時に自動的にスキップされます:
アイテムが TTL を超えると、取得時に自動的にスキップされます
```python
# Items older than TTL are silently ignored
+128 -93
View File
@@ -4,11 +4,11 @@ search:
---
# セッション
Agents SDK は、複数のエージェント実行にまたがって会話履歴を自動的に維持する組み込みのセッションメモリを提供しており、ターン間で `.to_input_list()` を手動で扱う必要をなくします。
Agents SDK は、複数のエージェント実行にまたがって会話履歴を自動的に維持する組み込みのセッションメモリを提供し、ターン間で `.to_input_list()` を手動で扱う必要をなくします。
Sessions は特定のセッションの会話履歴を保存し、明示的な手動メモリ管理を必要とせずにエージェントがコンテキストを維持できるようにします。これは、エージェントに過去のやり取りを記憶させたいチャットアプリケーションや複数ターンの会話を構築するに特に有用です。
セッションは特定のセッションの会話履歴を保存し、明示的な手動メモリ管理を必要とせずにエージェントがコンテキストを維持できるようにします。これは、エージェントに以前のやり取りを覚えておいてほしいチャットアプリケーションや複数ターンの会話を構築する場合に特に便利です。
SDK にクライアント側メモリ管理を任せたい場合は sessions を使用してください。Sessions は同一実行内で `conversation_id``previous_response_id``auto_previous_response_id` と組み合わせることはできません。代わりに OpenAI のサーバー管理による継続を使たい場合は、session を重ねるのではなくそれらの仕組みのいずれかを選択してください。
SDK にクライアント側メモリ管理せたい場合は、セッションを使用します。セッションは、同じ実行内で `conversation_id``previous_response_id`または `auto_previous_response_id` と組み合わせることはできません。代わりに OpenAI のサーバー管理による継続を使用したい場合は、セッションを重ねて使うのではなくそれらの仕組みのいずれかを選択してください。
## クイックスタート
@@ -49,9 +49,9 @@ result = Runner.run_sync(
print(result.final_output) # "Approximately 39 million"
```
## 同セッションで中断実行再開
## 同セッションによる中断された実行再開
実行が承認待ちで一時停止した場合は、同じ session インスタンス(または同じバックエンドストアを指す別の session インスタンス)で再開してください。そうすることで、再開たターン同じ保存済み会話履歴を継続します。
実行が承認待ちで一時停止した場合は、同じセッションインスタンス(または同じバッキングストアを指す別のセッションインスタンス)で再開し、再開されたターン同じ保存済み会話履歴を継続するようにします。
```python
result = await Runner.run(agent, "Delete temporary files that are no longer needed.", session=session)
@@ -63,31 +63,31 @@ if result.interruptions:
result = await Runner.run(agent, state, session=session)
```
## セッションのコア動作
## コアセッション動作
セッションメモリが有効な場合:
1. **各実行前**: runner はセッションの会話履歴を自動取得し、入力アイテムの先頭に追加します。
2. **各実行後**: 実行中に生成されたすべての新アイテム(ユーザー入力、assistant 応答、ツール呼び出しなど)が自動的にセッション保存されます。
3. **コンテキスト保持**: 同じ session を使う後続の各実行には完全な会話履歴が含まれ、エージェントコンテキストを維持できます。
1. **各実行**: ランナーはセッションの会話履歴を自動的に取得し、入力アイテムのに追加します。
2. **各実行**: 実行中に生成されたすべての新しいアイテム(ユーザー入力、アシスタントの応答、ツール呼び出しなど)がセッションに自動的に保存されます。
3. **コンテキスト保持**: 同じセッションでの後続の各実行には完全な会話履歴が含まれるため、エージェントコンテキストを維持できます。
これにより、`.to_input_list()` を手動で呼び出し実行間の会話状態を管理する必要がなくなります。
これにより、`.to_input_list()` を手動で呼び出したり、実行間の会話状態を管理したりする必要がなくなります。
## 履歴と新入力のマージ方法の制御
## 履歴と新しい入力のマージ方法の制御
session を渡すと、runner は通常次のようにモデル入力を準備します:
セッションを渡すと、ランナーは通常、モデル入力を次のように準備します
1. セッション履歴(`session.get_items(...)` から取得)
2. 新しいターン入力
2. 新しいターン入力
モデル呼び出しのこのマージ処理をカスタマイズするには [`RunConfig.session_input_callback`][agents.run.RunConfig.session_input_callback] を使用します。コールバックは 2 つのリストを受け取ります:
モデル呼び出しの前にこのマージ手順をカスタマイズするには[`RunConfig.session_input_callback`][agents.run.RunConfig.session_input_callback] を使用します。コールバックは次の 2 つのリストを受け取ります
- `history`: 取得されたセッション履歴(すでに入力アイテム形式に正規化済み)
- `new_input`: 現在ターンの新しい入力アイテム
- `new_input`: 現在ターンの新しい入力アイテム
モデルに送信する最終的な入力アイテムのリストを返してください
モデルに送信する最終的な入力アイテムのリストを返します
コールバックは両方のリストのコピーを受け取るため、安全に変更できます。返されたリストはそのターンのモデル入力を制御しますが、SDK が永続化するのは引き続き新しいターンに属するアイテムのみです。したがって、古い履歴を並べ替えたりフィルタしたりしても、古いセッションアイテムが新しい入力として再保存されることはありません。
コールバックは両方のリストのコピーを受け取るため、安全に変更できます。返されたリストはそのターンのモデル入力を制御しますが、SDK 新しいターンに属するアイテムのみを永続化します。そのため、古い履歴を並べ替えたりフィルタリングしたりしても、古いセッションアイテムが新しい入力として再保存されることはありません。
```python
from agents import Agent, RunConfig, Runner, SQLiteSession
@@ -109,16 +109,16 @@ result = await Runner.run(
)
```
これは、セッションの保存方法を変更せずに、履歴のカスタムな間引き、並べ替え、または選択的な取り込みが必要な場合に使用します。モデル呼び出し直前にさらに後段の最終処理が必要な場合は、[running agents guide](../running_agents.md) の [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter] を使用してください。
セッションがアイテムを保存する方法を変更せずに、カスタムの枝刈り、並べ替え、または履歴の選択的な取り込みが必要な場合に使用します。モデル呼び出し直前にさらに最終的な処理が必要な場合は、[エージェント実行ガイド](../running_agents.md)の [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter] を使用してください。
## 取得履歴の制限
## 取得する履歴の制限
各実行前にどの程度の履歴を取得するかを制御するには [`SessionSettings`][agents.memory.SessionSettings] を使用します。
各実行前に取得する履歴の量を制御するには[`SessionSettings`][agents.memory.SessionSettings] を使用します。
- `SessionSettings(limit=None)`(デフォルト): 利用可能なセッションアイテムをすべて取得
- `SessionSettings(limit=N)`: 直近 `N` 件のアイテムのみ取得
- `SessionSettings(limit=None)`(デフォルト): 利用可能なすべてのセッションアイテムを取得します
- `SessionSettings(limit=N)`: 直近 `N` アイテムのみ取得します
これは [`RunConfig.session_settings`][agents.run.RunConfig.session_settings] 実行ごとに適用できます:
これは[`RunConfig.session_settings`][agents.run.RunConfig.session_settings] を介して実行ごとに適用できます
```python
from agents import Agent, RunConfig, Runner, SessionSettings, SQLiteSession
@@ -134,13 +134,13 @@ result = await Runner.run(
)
```
セッション実装がデフォルトの session settings を公開している場合、`RunConfig.session_settings` はその実行にいて `None` 以外の値を上書きします。これは、セッションのデフォルト動作を変更せずに取得サイズ上限を設けたい長い会話で有用です。
セッション実装がデフォルトのセッション設定を公開している場合、`RunConfig.session_settings` はその実行にいて `None` ではない値を上書きします。これは、セッションのデフォルト動作を変更せずに取得サイズ上限設定したい長い会話で便利です。
## メモリ操作
### 基本操作
Sessions は会話履歴を管理するための複数の操作をサポートしています:
セッションは、会話履歴を管理するためのいくつかの操作をサポートしています
```python
from agents import SQLiteSession
@@ -167,7 +167,7 @@ await session.clear_session()
### 修正のための pop_item の使用
`pop_item` メソッドは、会話の最後のアイテムを取り消したり変更したりしたい場合に特に有用です:
`pop_item` メソッドは、会話の最後のアイテムを取り消したり変更したりしたい場合に特に便利です
```python
from agents import Agent, Runner, SQLiteSession
@@ -202,27 +202,28 @@ SDK は、さまざまなユースケース向けに複数のセッション実
### 組み込みセッション実装の選択
以下の詳細な例を読む前に、この表を使って開始点を選んでください。
以下の詳細な例を読む前に、開始点を選ぶためにこの表を使用してください。
| Session type | Best for | Notes |
| セッションタイプ | 最適な用途 | 注記 |
| --- | --- | --- |
| `SQLiteSession` | ローカル開発とシンプルなアプリ | 組み込み、軽量、ファイル永続化またはインメモリ |
| `AsyncSQLiteSession` | `aiosqlite` を使た非同期 SQLite | 非同期ドライバー対応の拡張バックエンド |
| `RedisSession` | ワーカー / サービス間で共有メモリ | 低レイテンシ分散デプロイに適しています |
| `SQLAlchemySession` | 既存データベースを持つ本番アプリ | SQLAlchemy 対応データベースで動作 |
| `DaprSession` | Dapr sidecar を使うクラウドネイティブデプロイ | 複数の state store に加え TTL と整合性制御をサポート |
| `OpenAIConversationsSession` | OpenAI でのサーバー管理ストレージ | OpenAI Conversations API ベースの履歴 |
| `OpenAIResponsesCompactionSession` | 自動圧縮付きの長い会話 | 別のセッションバックエンドをラップ |
| `AdvancedSQLiteSession` | 分岐 / 分析機能付き SQLite | 機能セットが大きめ。専用ページを参照 |
| `EncryptedSession` | 別セッションの上に暗号化 + TTL | ラッパー。先に基盤バックエンドを選択 |
| `SQLiteSession` | ローカル開発とシンプルなアプリ | 組み込み、軽量、ファイルバックまたはインメモリ |
| `AsyncSQLiteSession` | `aiosqlite` を使用した非同期 SQLite | 非同期ドライバー対応の拡張バックエンド |
| `RedisSession` | ワーカーサービス間で共有するメモリ | 低レイテンシ分散デプロイに適しています |
| `SQLAlchemySession` | 既存データベースを使用する本番アプリ | SQLAlchemy がサポートするデータベースで動作します |
| `MongoDBSession` | すでに MongoDB を使用しているアプリ、またはマルチプロセスストレージが必要なアプリ | 非同期 pymongo;順序付け用のアトミックシーケンスカウンター |
| `DaprSession` | Dapr サイドカーを使用するクラウドネイティブデプロイ | 複数のステートストアに加え、TTL と整合性制御をサポートします |
| `OpenAIConversationsSession` | OpenAI でのサーバー管理ストレージ | OpenAI Conversations API をバックエンドとする履歴 |
| `OpenAIResponsesCompactionSession` | 自動圧縮を伴う長い会話 | 別のセッションバックエンドをラップします |
| `AdvancedSQLiteSession` | SQLite に加えて分岐や分析 | より多機能です。専用ページを参照してください |
| `EncryptedSession` | 別のセッション上での暗号化と TTL | ラッパーです。まず基盤となるバックエンドを選択してください |
一部の実装には追加の詳細を説明した専用ページがありそれらは各サブセクション内でリンクされています。
一部の実装には追加の詳細を含む専用ページがあります。それらは各サブセクション内でリンクされています。
ChatKit 用の Python サーバーを実装る場合は、ChatKit のスレッドとアイテム永続化に `chatkit.store.Store` 実装を使用してください。`SQLAlchemySession` などの Agents SDK セッションは SDK 側の会話履歴を管理しますが、ChatKit の store のそのままの置き換えにはなりません。[ChatKit データストアの実装に関する `chatkit-python` ガイド](https://github.com/openai/chatkit-python/blob/main/docs/guides/respond-to-user-message.md#implement-your-chatkit-data-store) を参照してください。
ChatKit 用の Python サーバーを実装している場合は、ChatKit のスレッドとアイテム永続化に `chatkit.store.Store` 実装を使用してください。`SQLAlchemySession` などの Agents SDK セッションは SDK 側の会話履歴を管理しますが、ChatKit のストアのドロップイン置き換えではありません。[ChatKit データストアの実装に関する `chatkit-python` ガイド](https://github.com/openai/chatkit-python/blob/main/docs/guides/respond-to-user-message.md#implement-your-chatkit-data-store)を参照してください。
### OpenAI Conversations API セッション
`OpenAIConversationsSession` を通じて [OpenAI's Conversations API](https://platform.openai.com/docs/api-reference/conversations) を使用します。
`OpenAIConversationsSession` を通じて [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations)を使用します。
```python
from agents import Agent, Runner, OpenAIConversationsSession
@@ -258,7 +259,7 @@ print(result.final_output) # "California"
### OpenAI Responses 圧縮セッション
Responses API`responses.compact`)で保存済み会話履歴を圧縮するには `OpenAIResponsesCompactionSession` を使用します。これは基盤となる session をラップし、`should_trigger_compaction` に基づいて各ターン後に自動圧縮できます。`OpenAIConversationsSession` をこれでラップしないでください。これら 2 つの機能は履歴を異なる方法で管理します。
Responses API`responses.compact`)で保存済み会話履歴を圧縮するには`OpenAIResponsesCompactionSession` を使用します。これは基盤となるセッションをラップし、`should_trigger_compaction` に基づいて各ターン後に自動的に圧縮できます。`OpenAIConversationsSession` をこれでラップしないでください。こ 2 つの機能は異なる方法で履歴を管理します。
#### 一般的な使用方法(自動圧縮)
@@ -277,17 +278,17 @@ result = await Runner.run(agent, "Hello", session=session)
print(result.final_output)
```
デフォルトでは、候補しきい値に達すると各ターン後に圧縮が実行されます。
デフォルトでは、候補しきい値に達すると各ターン後に圧縮が実行されます。
`compaction_mode="previous_response_id"` は、すでに Responses API の response ID でターンを連結している場合に最適です。`compaction_mode="input"` は代わりに現在のセッションアイテムから圧縮リクエストを再構築します。これは response chain が利用できない場合や、セッション内容を信頼できる唯一の情報源にしたい場合に有用です。デフォルトの `"auto"` は、利用可能な中で最も安全な選択肢を選びます。
`compaction_mode="previous_response_id"` は、Responses API の応答 ID でターンをすでに連鎖させている場合に最も適しています。`compaction_mode="input"`代わりに現在のセッションアイテムから圧縮リクエストを再構築します。これは、応答チェーンが利用できない場合や、セッション内容を信頼できる情報源にしたい場合に便利です。デフォルトの `"auto"` は、利用可能な中で最も安全な選択肢を選びます。
エージェント実行で `ModelSettings(store=False)` を使うと、Responses API は後で参照するための最新 response を保持しません。このステートレス構成では、デフォルトの `"auto"` モードは `previous_response_id` に依存せず、入力ベース圧縮にフォールバックします。完全な例[`examples/memory/compaction_session_stateless_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/compaction_session_stateless_example.py) を参照してください。
エージェント `ModelSettings(store=False)` で実行される場合、Responses API は後で検索するための最後の応答を保持しません。このステートレス構成では、デフォルトの `"auto"` モードは `previous_response_id` に依存するのではなく、入力ベース圧縮にフォールバックします。完全な例については、[`examples/memory/compaction_session_stateless_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/compaction_session_stateless_example.py) を参照してください。
#### 自動圧縮はストリーミングブロックする場合があります
#### auto-compaction によるストリーミングブロック
圧縮はセッション履歴をクリアして書き込みするため、SDK は圧縮完了前に実行完了と見なしません。ストリーミングモードでは、圧縮が重い場合、最後の出力トークンの後も `run.stream_events()` が数秒開いたままになることがあります。
圧縮はセッション履歴をクリアして書き換えるため、SDK は実行完了とみなす前に圧縮の完了を待ちます。ストリーミングモードでは、圧縮が重い場合、最後の出力トークンの後も `run.stream_events()` が数秒開いたままになることがあります。
低レイテンシストリーミングや高速なターン交代が必要な場合は、自動圧縮を無効し、ターン間(またはアイドル時間)に `run_compaction()`手動で呼び出してください。圧縮を強制するタイミングは独自の基準で決められます。
低レイテンシストリーミングや高速なターン処理が必要な場合は、自動圧縮を無効し、ターン間(またはアイドル時間)に自分で `run_compaction()` を呼び出してください。独自の基準に基づいて、いつ圧縮を強制するかを決めることができます。
```python
from agents import Agent, Runner, SQLiteSession
@@ -310,7 +311,7 @@ await session.run_compaction({"force": True})
### SQLite セッション
SQLite を使用したデフォルトの軽量セッション実装です:
SQLite を使用するデフォルトの軽量セッション実装です
```python
from agents import SQLiteSession
@@ -331,7 +332,7 @@ result = await Runner.run(
### 非同期 SQLite セッション
`aiosqlite` をバックエンドにした SQLite 永続化が必要な場合は `AsyncSQLiteSession` を使用します。
`aiosqlite` をバックエンドとする SQLite 永続化が必要な場合は`AsyncSQLiteSession` を使用します。
```bash
pip install aiosqlite
@@ -348,7 +349,7 @@ result = await Runner.run(agent, "Hello", session=session)
### Redis セッション
複数のワーカーサービス間でセッションメモリを共有するには `RedisSession` を使用します。
複数のワーカーまたはサービス間で共有セッションメモリを使用するには`RedisSession` を使用します。
```bash
pip install openai-agents[redis]
@@ -368,7 +369,7 @@ result = await Runner.run(agent, "Hello", session=session)
### SQLAlchemy セッション
SQLAlchemy 対応の任意のデータベースを使用した、本番対応の Agents SDK セッション永続化:
SQLAlchemy がサポートする任意のデータベースを使用した、本番対応の Agents SDK セッション永続化です。
```python
from agents.extensions.memory import SQLAlchemySession
@@ -386,11 +387,11 @@ engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
session = SQLAlchemySession("user_123", engine=engine, create_tables=True)
```
詳細[SQLAlchemy Sessions](sqlalchemy_session.md) を参照してください。
詳細なドキュメントについては、[SQLAlchemy セッション](sqlalchemy_session.md)を参照してください。
### Dapr セッション
すでに Dapr sidecar を運用している場合、またはエージェントコードを変更せずに異なる state-store バックエンド間で移行可能なセッションストレージが必要な場合は `DaprSession` を使用します。
すでに Dapr サイドカーを実行している場合、またはエージェントコードを変更せずに異なるステートストアバックエンドへ移行できるセッションストレージが必要な場合は`DaprSession` を使用します。
```bash
pip install openai-agents[dapr]
@@ -411,18 +412,50 @@ async with DaprSession.from_address(
print(result.final_output)
```
:
:
- `from_address(...)` は Dapr クライアントを作成し所有します。アプリすでに管理している場合は、`dapr_client=...` を指定して直接 `DaprSession(...)` を構築してください。
- 基盤 state store が TTL をサポートしている場合`ttl=...` を渡すと古いセッションデータを自動期限切れにできます。
- より強い read-after-write 保証が必要な場合は `consistency=DAPR_CONSISTENCY_STRONG` を渡してください
- Dapr Python SDK は HTTP sidecar endpoint も確認します。ローカル開発では、`dapr_address` で使用する gRPC ポートに加えて、`--dapr-http-port 3500` でも Dapr を起動してください。
- ローカルコンポーネントやトラブルシューティングを含む完全なセットアップ手順[`examples/memory/dapr_session_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/dapr_session_example.py) を参照してください。
- `from_address(...)` は Dapr クライアントを作成し所有します。アプリすでにクライアントを管理している場合は、`dapr_client=...` を指定して `DaprSession(...)`直接構築してください。
- 基盤となるステートストアが TTL をサポートしている場合古いセッションデータを自動的に期限切れにするには、`ttl=...` を渡します。
- より強い read-after-write 保証が必要な場合は`consistency=DAPR_CONSISTENCY_STRONG` を渡します
- Dapr Python SDK は HTTP サイドカーエンドポイントもチェックします。ローカル開発では、`dapr_address` で使用する gRPC ポートに加えて、`--dapr-http-port 3500` でも Dapr を起動してください。
- ローカルコンポーネントやトラブルシューティングを含む完全なセットアップ手順については、[`examples/memory/dapr_session_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/dapr_session_example.py) を参照してください。
### Advanced SQLite セッション
### MongoDB セッション
会話分岐、使用状況分析、構造化クエリを備えた拡張 SQLite セッション:
すでに MongoDB を使用しているアプリケーション、または水平スケーラブルでマルチプロセス対応のセッションストレージが必要なアプリケーションには、`MongoDBSession` を使用します。
```bash
pip install openai-agents[mongodb]
```
```python
from agents import Agent, Runner
from agents.extensions.memory import MongoDBSession
agent = Agent(name="Assistant")
# Create from URI — owns the client and closes it when session.close() is called
session = MongoDBSession.from_uri(
"user-123",
uri="mongodb://localhost:27017",
database="agents",
)
result = await Runner.run(agent, "Hello", session=session)
print(result.final_output)
await session.close()
```
注記:
- `from_uri(...)``AsyncMongoClient` を作成し、所有し、`session.close()` で閉じます。アプリケーションがすでにクライアントを管理している場合は、`client=...` を指定して `MongoDBSession(...)` を直接構築してください。その場合、`session.close()` は no-op となり、ライフサイクルは呼び出し元が保持します。
- ほかの変更なしに、`from_uri(...)``mongodb+srv://user:password@cluster.example.mongodb.net` URI を渡すことで [MongoDB Atlas](https://www.mongodb.com/products/platform) に接続できます。
- 2 つのコレクションが使用され、どちらの名前も `sessions_collection=`(デフォルトは `agent_sessions`)と `messages_collection=`(デフォルトは `agent_messages`)で設定できます。インデックスは初回使用時に自動的に作成されます。各メッセージドキュメントは、同時実行の書き込み元やプロセスをまたいで順序を保持する単調増加の `seq` カウンターを持ちます。
- 最初の実行前に接続性を確認するには、`await session.ping()` を使用します。
### 高度な SQLite セッション
会話の分岐、使用状況分析、構造化クエリを備えた拡張 SQLite セッションです。
```python
from agents.extensions.memory import AdvancedSQLiteSession
@@ -442,11 +475,11 @@ await session.store_run_usage(result) # Track token usage
await session.create_branch_from_turn(2) # Branch from turn 2
```
詳細は [Advanced SQLite Sessions](advanced_sqlite_session.md) を参照してください。
詳細なドキュメントについては、[高度な SQLite セッション](advanced_sqlite_session.md)を参照してください。
### Encrypted セッション
### 暗号化セッション
任意のセッション実装向け透過的暗号化ラッパー:
任意のセッション実装向け透過的暗号化ラッパーです。
```python
from agents.extensions.memory import EncryptedSession, SQLAlchemySession
@@ -469,33 +502,34 @@ session = EncryptedSession(
result = await Runner.run(agent, "Hello", session=session)
```
詳細は [Encrypted Sessions](encrypted_session.md) を参照してください。
詳細なドキュメントについては、[暗号化セッション](encrypted_session.md)を参照してください。
### その他のセッションタイプ
このほかにもいくつかの組み込みオプションがあります。`examples/memory/``extensions/memory/` 下のソースコードを参照してください。
組み込みの選択肢はほかにもいくつかあります。`examples/memory/``extensions/memory/` 下のソースコードを参照してください。
## 運用パターン
### セッション ID 命名
### セッション ID 命名
会話整理に役立つ、意味のあるセッション ID を使用してください:
会話整理しやすい、意味のあるセッション ID を使用してください
- ユーザーベース: `"user_12345"`
- スレッドベース: `"thread_abc123"`
- コンテキストベース: `"support_ticket_456"`
### メモリ永続化
### メモリ永続化
- 一時的な会話にはインメモリ SQLite(`SQLiteSession("session_id")`)を使用
- 永続的な会話にはファイルベース SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)を使用
- `aiosqlite` ベース実装が必要な場合は非同期 SQLite(`AsyncSQLiteSession("session_id", db_path="...")`)を使用
- 共有低レイテンシセッションメモリには Redis バックエンドセッション(`RedisSession.from_url("session_id", url="redis://...")`)を使用
- SQLAlchemy が対応する既存データベースを持つ本番システムには SQLAlchemy ベースセッション(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`を使用
- 組み込みテレメトリ、トレーシング、データ分離に加え 30 以上のデータベースバックエンドをサポートする本番クラウドネイティブデプロイには Dapr state store セッション(`DaprSession.from_address("session_id", state_store_name="statestore", dapr_address="localhost:50001")`)を使用
- 履歴を OpenAI Conversations API に保存したい場合は OpenAI ホスト型ストレージ(`OpenAIConversationsSession()`)を使用
- 任意のセッションを透過的暗号化と TTL ベース期限切れでラップするには暗号化セッション(`EncryptedSession(session_id, underlying_session, encryption_key)`)を使用
- より高度なユースケース向けに、他の本番システム(例: Django)向けカスタムセッションバックエンドの実装も検討してください
- 一時的な会話にはインメモリ SQLite(`SQLiteSession("session_id")`)を使用します
- 永続的な会話にはファイルベース SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)を使用します
- `aiosqlite` ベース実装が必要な場合は非同期 SQLite`AsyncSQLiteSession("session_id", db_path="...")`)を使用します
- 共有された低レイテンシセッションメモリにはRedis バックセッション(`RedisSession.from_url("session_id", url="redis://...")`)を使用します
- SQLAlchemy がサポートする既存データベースを持つ本番システムにはSQLAlchemy を利用したセッション(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) を使用します
- すでに MongoDB を使用しているアプリケーション、またはマルチプロセスで水平スケーラブルなセッションストレージが必要なアプリケーションには、MongoDB セッション(`MongoDBSession.from_uri("session_id", uri="mongodb://localhost:27017")`)を使用します
- 組み込みのテレメトリ、トレーシング、データ分離を備えた 30 以上のデータベースバックエンドをサポートする本番クラウドネイティブデプロイには、Dapr ステートストアセッション(`DaprSession.from_address("session_id", state_store_name="statestore", dapr_address="localhost:50001")`)を使用します
- OpenAI Conversations API に履歴を保存したい場合は、OpenAI がホストするストレージ(`OpenAIConversationsSession()`)を使用します
- 透過的な暗号化と TTL ベースの有効期限で任意のセッションをラップするには、暗号化セッション(`EncryptedSession(session_id, underlying_session, encryption_key)`)を使用します
- より高度なユースケースでは、ほかの本番システム(たとえば Django)向けのカスタムセッションバックエンドの実装を検討してください
### 複数セッション
@@ -543,7 +577,7 @@ result2 = await Runner.run(
## 完全な例
セッションメモリの動作を示す完全な例です:
セッションメモリの動作を示す完全な例を以下に示します。
```python
import asyncio
@@ -607,7 +641,7 @@ if __name__ == "__main__":
## カスタムセッション実装
[`Session`][agents.memory.session.Session] プロトコルに従うクラスを作成することで、独自のセッションメモリを実装できます:
[`Session`][agents.memory.session.Session] プロトコルに従うクラスを作成することで、独自のセッションメモリを実装できます
```python
from agents.memory.session import SessionABC
@@ -650,27 +684,28 @@ result = await Runner.run(
)
```
## コミュニティセッション実装
## コミュニティによるセッション実装
コミュニティは追加のセッション実装開発されています:
コミュニティは追加のセッション実装開発ています
| Package | Description |
| パッケージ | 説明 |
|---------|-------------|
| [openai-django-sessions](https://pypi.org/project/openai-django-sessions/) | 任意の Django 対応データベース( PostgreSQL、 MySQL、 SQLite など)向けの Django ORM ベースセッション |
| [openai-django-sessions](https://pypi.org/project/openai-django-sessions/) | 任意の Django 対応データベース(PostgreSQL、MySQL、SQLite など)向けの Django ORM ベースセッション |
セッション実装を作成した場合は、ここに追加するためのドキュメント PR をぜひ送ってください。
セッション実装を構築した場合は、ぜひドキュメント PR を送ってここに追加してください。
## API リファレンス
詳細な API ドキュメント以下を参照してください:
詳細な API ドキュメントについては、以下を参照してください
- [`Session`][agents.memory.session.Session] - プロトコルインターフェ
- [`Session`][agents.memory.session.Session] - プロトコルインターフェ
- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API 実装
- [`OpenAIResponsesCompactionSession`][agents.memory.openai_responses_compaction_session.OpenAIResponsesCompactionSession] - Responses API 圧縮ラッパー
- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 基本 SQLite 実装
- [`AsyncSQLiteSession`][agents.extensions.memory.async_sqlite_session.AsyncSQLiteSession] - `aiosqlite` ベースの非同期 SQLite 実装
- [`RedisSession`][agents.extensions.memory.redis_session.RedisSession] - Redis バックエンドセッション実装
- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy ベース実装
- [`DaprSession`][agents.extensions.memory.dapr_session.DaprSession] - Dapr state store 実装
- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 基本的な SQLite 実装
- [`AsyncSQLiteSession`][agents.extensions.memory.async_sqlite_session.AsyncSQLiteSession] - `aiosqlite` に基づく非同期 SQLite 実装
- [`RedisSession`][agents.extensions.memory.redis_session.RedisSession] - Redis バックセッション実装
- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy を利用した実装
- [`MongoDBSession`][agents.extensions.memory.mongodb_session.MongoDBSession] - MongoDB バックのセッション実装
- [`DaprSession`][agents.extensions.memory.dapr_session.DaprSession] - Dapr ステートストア実装
- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 分岐と分析を備えた拡張 SQLite
- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 任意のセッション向け暗号化ラッパー
- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 任意のセッション向け暗号化ラッパー
+6 -6
View File
@@ -4,11 +4,11 @@ search:
---
# SQLAlchemy セッション
`SQLAlchemySession` は SQLAlchemy を使用して本番運用対応のセッション実装を提供し、セッションストレージ SQLAlchemy がサポートする任意のデータベース ( PostgreSQLMySQLSQLite など ) を使用できます。
`SQLAlchemySession` は SQLAlchemy を使用して本番環境に対応したセッション実装を提供します。これにより、セッションストレージとして SQLAlchemy がサポートする任意のデータベース (PostgreSQLMySQLSQLite など) を使用できます。
## インストール
SQLAlchemy セッションには `sqlalchemy` extra が必要です
SQLAlchemy セッションには `sqlalchemy` extra が必要です:
```bash
pip install openai-agents[sqlalchemy]
@@ -18,7 +18,7 @@ pip install openai-agents[sqlalchemy]
### データベース URL の使用
開始する最も簡単な方法です
始めるための最も簡単な方法です:
```python
import asyncio
@@ -42,9 +42,9 @@ if __name__ == "__main__":
asyncio.run(main())
```
### 既存 engine の使用
### 既存エンジンの使用
既存の SQLAlchemy engine があるアプリケーション向けです
既存の SQLAlchemy エンジンを持つアプリケーション向けです:
```python
import asyncio
@@ -77,4 +77,4 @@ if __name__ == "__main__":
## API リファレンス
- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - メインクラス
- [`Session`][agents.memory.session.Session] - ベースセッションプロトコル
- [`Session`][agents.memory.session.Session] - 基本セッションプロトコル
+22 -22
View File
@@ -4,19 +4,19 @@ search:
---
# ストリーミング
ストリーミングを使うと、エージェントの実行が進行する間の更新を購読できます。これは、エンドユーザーに進捗更新や部分的な応答を表示するに役立ちます。
ストリーミングにより、エージェントの実行が進むにつれて更新を購読できます。これは、エンドユーザーに進捗状況の更新や部分的なレスポンスを表示する場合に役立ちます。
ストリーミングするには、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を呼び出します。これにより [`RunResultStreaming`][agents.result.RunResultStreaming] が得られます。`result.stream_events()` を呼び出すと、以下で説明する [`StreamEvent`][agents.stream_events.StreamEvent] オブジェクトの非同期ストリームが得られます。
ストリーミングするには、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を呼び出します。これにより [`RunResultStreaming`][agents.result.RunResultStreaming] が返されます。`result.stream_events()` を呼び出すと、以下で説明する [`StreamEvent`][agents.stream_events.StreamEvent] オブジェクトの非同期ストリームが得られます。
非同期イテレーターが終了するまで `result.stream_events()` 消費続けてください。ストリーミング実行は、イテレーターが終了するまで完了しません。また、セッション永続化、承認の記録管理、履歴の圧縮といった後処理は、最後の可視トークン到着後に完了する場合があります。ループを抜けた時点で`result.is_complete` 最終的な実行状態を反映します。
非同期イテレーターが終了するまで`result.stream_events()` 消費続けてください。ストリーミング実行は、イテレーターが終了するまで完了しません。また、セッション永続化、承認の記録管理、履歴の圧縮などの後処理は、最後の可視トークン到着した後に完了する場合があります。ループが終了すると`result.is_complete` 最終的な実行状態を反映します。
## raw response イベント
## raw レスポンスイベント
[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] は、LLM から直接渡される raw イベントです。これらは OpenAI Responses API 形式であり、各イベントはタイプ`response.created``response.output_text.delta` など)とデータを持ちます。これらのイベントは、生成され次第すぐにレスポンスメッセージユーザーストリーミングしたい場合に有用です。
[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] は、LLM から直接渡される raw イベントです。これらは OpenAI Responses API 形式であり、各イベントには型`response.created``response.output_text.delta` など)とデータがあります。これらのイベントは、レスポンスメッセージが生成され次第、ユーザーストリーミングしたい場合に役立ちます。
コンピュータツールの raw イベントは、保存済み結果と同じ preview と GA の区別を維持します。Preview フローでは 1 つの `action`含む `computer_call` アイテムをストリーミングし、`gpt-5.4` ではバッチ化された `actions[]`含む `computer_call` アイテムをストリーミングできます。より高レベルの [`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] サーフェスは、このためコンピュータ専用イベント名追加されません。どちらの形も引き続き `tool_called` として表し、スクリーンショット結果は `computer_call_output` アイテムをラップした `tool_output` として返されます。
コンピュータツールの raw イベントは、保存された実行結果と同じ preview と GA の区別を維持します。Preview フローでは1 つの `action`持つ `computer_call` アイテムをストリーミングします。一方`gpt-5.5` ではバッチ化された `actions[]`持つ `computer_call` アイテムをストリーミングできます。高レベルの [`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] サーフェスは、このために特別なコンピュータ専用イベント名追加ません。どちらの形も引き続き `tool_called` として表面化し、スクリーンショットの実行結果は `computer_call_output` アイテムをラップする `tool_output` として返されます。
たとえば、これは LLM が生成するテキストをトークン単位で出力します。
たとえば、これは LLM によって生成されたテキストをトークンごとに出力します。
```python
import asyncio
@@ -41,7 +41,7 @@ if __name__ == "__main__":
## ストリーミングと承認
ストリーミングは、ツール承認のために一時停止する実行と互換性があります。ツールに承認が必要な場合、`result.stream_events()` は終了し、保留中の承認は [`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] 公開されます。`result.to_state()` 結果を [`RunState`][agents.run_state.RunState] に変換し、割り込みを承認または拒否してから、`Runner.run_streamed(...)` で再開します。
ストリーミングは、ツール承認のために一時停止する実行と互換性があります。ツールに承認が必要な場合、`result.stream_events()` は終了し、保留中の承認は [`RunResultStreaming.interruptions`][agents.result.RunResultStreaming.interruptions] 公開されます。`result.to_state()` を使って実行結果を [`RunState`][agents.run_state.RunState] に変換し、中断を承認または拒否してから、`Runner.run_streamed(...)` で再開します。
```python
result = Runner.run_streamed(agent, "Delete temporary files if they are no longer needed.")
@@ -57,25 +57,25 @@ if result.interruptions:
pass
```
一時停止 / 再開の完全な手順は、[human-in-the-loop ガイド](human_in_the_loop.md) を参照してください。
一時停止/再開の完全なウォークスルーについては、[human-in-the-loop ガイド](human_in_the_loop.md)を参照してください。
## 現在のターン後のストリーミングキャンセル
## 現在のターン後のストリーミングキャンセル
ストリーミング実行を途中で停止する必要がある場合は、[`result.cancel()`][agents.result.RunResultStreaming.cancel] を呼び出します。デフォルトでは、これにより実行は即時停止します。停止前に現在のターンをきれいに完了させるには、代わりに `result.cancel(mode="after_turn")` を呼び出してください
途中でストリーミング実行を停止する必要がある場合は、[`result.cancel()`][agents.result.RunResultStreaming.cancel] を呼び出します。デフォルトでは、これにより実行はすぐに停止します。停止する前に現在のターンを正常に完了させるには、代わりに `result.cancel(mode="after_turn")` を呼び出します
ストリーミング実行は、`result.stream_events()` が終了するまで完了しません。SDK は、最後の可視トークンの後も、セッション項目の永続化、承認状態確定、履歴圧縮を続ける場合があります。
ストリーミング実行は、`result.stream_events()` が終了するまで完了しません。最後の可視トークンの後も、SDK がセッションアイテムを永続化したり、承認状態確定したり、履歴圧縮したりしている場合があります。
[`result.to_input_list(mode="normalized")`][agents.result.RunResultBase.to_input_list] から手動で継続していて`cancel(mode="after_turn")` がツールターン後に停止した場合は、新しいユーザーターンをすぐ追加するのではなく、その正規化済み入力で `result.last_agent` を再実行して未完了ターンを継続してください。
- ストリーミング実行がツール承認停止した場合、それを新しいターンとして扱わないでください。ストリームの消費を最後まで完了し、`result.interruptions` を確認してから`result.to_state()` から再開してください。
- 次のモデル呼び出し前に、取得したセッション履歴と新しいユーザー入力をどのようにマージするかをカスタマイズするには [`RunConfig.session_input_callback`][agents.run.RunConfig.session_input_callback] を使用します。そこで新ターン項目を書き換えた場合、そのターンで永続化されるのは書き換え後のバージョンです。
[`result.to_input_list(mode="normalized")`][agents.result.RunResultBase.to_input_list] から手動で継続しており`cancel(mode="after_turn")` がツールターンの後で停止した場合は、すぐに新しいユーザーターンを追加するのではなく、その正規化された入力で `result.last_agent` を再実行して未完了ターンを継続してください。
- ストリーミング実行がツール承認のために停止した場合、それを新しいターンとして扱わないでください。ストリームの読み出しを最後まで完了し、`result.interruptions` を確認して、代わりに `result.to_state()` から再開してください。
- 次のモデル呼び出し前に、取得したセッション履歴と新しいユーザー入力をどのようにマージするかをカスタマイズするには[`RunConfig.session_input_callback`][agents.run.RunConfig.session_input_callback] を使用します。そこで新しいターンのアイテムを書き換えた場合、その書き換え後のバージョンがそのターンとして永続化されます。
## 実行項目イベントとエージェントイベント
## 実行アイテムイベントとエージェントイベント
[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] はより高レベルのイベントです。項目が完全に生成されたときに通知します。これにより、各トークン単位ではなく、「メッセージ生成済み」「ツール実行済み」などのレベルで進捗更新を送ます。同様に、[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] は、現在のエージェントが変わったとき(例: ハンドオフの結果)に更新を提供します。
[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] はより高レベルのイベントです。アイテムが完全に生成されたタイミングを通知します。これにより、各トークン単位ではなく、「メッセージ生成された」「ツール実行された」などのレベルで進捗更新を送信できます。同様に、[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] は、現在のエージェントが変更されたとき(例: ハンドオフの結果として)に更新を提供します。
### 実行項目イベント名
### 実行アイテムイベント名
`RunItemStreamEvent.name` は、固定のセマンティックなイベント名セットを使用します。
`RunItemStreamEvent.name` は、固定された一連のセマンティックなイベント名を使用します。
- `message_output_created`
- `handoff_requested`
@@ -89,11 +89,11 @@ if result.interruptions:
- `mcp_approval_response`
- `mcp_list_tools`
`handoff_occured` は、後方互換性のため意図的にスペルミスのまます。
`handoff_occured` は、後方互換性のため意図的にスペルミスのままになっています。
ホストツール検索を使用する、モデルがツール検索リクエストを発行したときに `tool_search_called`発行され、Responses API が読み込まれたサブセットを返したときに `tool_search_output_created`発行されます。
ホストされたツール検索を使用する場合、モデルがツール検索リクエストを発行すると `tool_search_called`送出され、Responses API が読み込まれたサブセットを返すと `tool_search_output_created`送出されます。
たとえば、これは raw イベントを無視して、ユーザーへの更新をストリーミングします。
たとえば、これは raw イベントを無視し、更新をユーザーにストリーミングします。
```python
import asyncio
+173 -174
View File
@@ -4,39 +4,39 @@ search:
---
# ツール
ツールを使うと、エージェントはアクションを実行できます。たとえば、データ取得、コード実行、外部 API 呼び出し、さらにはコンピュータ操作などす。 SDK は 5 つのカテゴリーをサポートしています。
ツールを使用すると、データ取得、コード実行、外部 API 呼び出し、さらにはコンピュータ操作など、エージェントがさまざまなアクションを実行できます。SDK は、次の 5 つのカテゴリーをサポートしています。
- OpenAI がホストするツール: OpenAI サーバー上でモデルと並行して実行されます。
- ローカル / ランタイム実行ツール: `ComputerTool``ApplyPatchTool` は常にあなたの環境で実行され、`ShellTool` はローカルまたはホストコンテナで実行できます。
- Function Calling: 任意の Python 関数をツールとしてラップします。
- Agents as tools: 完全なハンドオフなしで、エージェントを呼び出し可能なツールとして公開します。
- Experimental: Codex tool: ツール呼び出しから、ワークスペーススコープ Codex タスクを実行します。
- OpenAI がホストするツールOpenAI サーバー上でモデルとともに実行されます。
- ローカルランタイム実行ツール`ComputerTool``ApplyPatchTool` は常にユーザーの環境で実行され、`ShellTool` はローカルまたはホストコンテナで実行できます。
- Function Calling任意の Python 関数をツールとしてラップします。
- Agents as tools完全なハンドオフを行わずに、エージェントを呼び出し可能なツールとして公開します。
- 実験的機能:Codex ツール:ツール呼び出しから、ワークスペーススコープされた Codex タスクを実行します。
## ツールタイプの選択
このページをカタログとして使い、次に自分が制御するランタイムに合うセクションへ進んでください。
このページをカタログとして使用し、制御するランタイムに該当するセクションへ移動してください。
| 次をしたい場合... | ここから開始 |
| 目的 | 参照先 |
| --- | --- |
| OpenAI 管理ツールを使う ( Web 検索、ファイル検索、Code Interpreter、ホスト型 MCP、画像生成 ) | [Hosted tools](#hosted-tools) |
| ツール検索で、実行時まで大規模なツール面を遅延させる | [Hosted tool search](#hosted-tool-search) |
| 自のプロセスまたは環境でツールを実行する | [Local runtime tools](#local-runtime-tools) |
| Python 関数をツールとしてラップする | [Function tools](#function-tools) |
| ハンドオフなしで、あるエージェントから別のエージェントを呼 | [Agents as tools](#agents-as-tools) |
| エージェントからワークスペーススコープ Codex タスクを実行する | [Experimental: Codex tool](#experimental-codex-tool) |
| OpenAI 管理するツールWeb 検索、ファイル検索、Code Interpreter、ホスト型 MCP、画像生成)を使用する | [ホスト型ツール](#hosted-tools) |
| ツール検索を使用して、大規模なツール群の読み込みをランタイムまで延期する | [ホスト型ツール検索](#hosted-tool-search) |
| 自のプロセスまたは環境でツールを実行する | [ローカルランタイムツール](#local-runtime-tools) |
| Python 関数をツールとしてラップする | [関数ツール](#function-tools) |
| ハンドオフを行わず、あるエージェントから別のエージェントを呼び出す | [Agents as tools](#agents-as-tools) |
| エージェントからワークスペーススコープされた Codex タスクを実行する | [実験的機能:Codex ツール](#experimental-codex-tool) |
## Hosted tools
## ホスト型ツール
[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] を使用する場合、 OpenAI はいくつかの組み込みツールを提供しています。
[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] を使用する場合、OpenAI はいくつかの組み込みツールを提供します。
- [`WebSearchTool`][agents.tool.WebSearchTool] 、エージェント Web 検索を行えるようにします。
- [`FileSearchTool`][agents.tool.FileSearchTool] は、 OpenAI ベクトルストアから情報を取得できるようにします。
- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] は、 LLM サンドボックス環境でコードを実行できるようにします。
- [`WebSearchTool`][agents.tool.WebSearchTool] を使用すると、エージェント Web 検索できます。
- [`FileSearchTool`][agents.tool.FileSearchTool] を使用すると、OpenAI ベクトルストアから情報を取得できます。
- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] を使用すると、LLM サンドボックス環境でコードを実行できます。
- [`HostedMCPTool`][agents.tool.HostedMCPTool] は、リモート MCP サーバーのツールをモデルに公開します。
- [`ImageGenerationTool`][agents.tool.ImageGenerationTool] は、プロンプトから画像を生成します。
- [`ToolSearchTool`][agents.tool.ToolSearchTool] は、モデルが必要に応じて遅延ツール、名前空間、またはホスト MCP サーバーを読み込めるようにします。
- [`ToolSearchTool`][agents.tool.ToolSearchTool] を使用すると、モデルは遅延読み込みされるツール、名前空間、またはホスト MCP サーバーをオンデマンドで読み込めます。
高度なホスト検索オプション:
ホスト検索の高度なオプション
- `FileSearchTool` は、`vector_store_ids``max_num_results` に加えて、`filters``ranking_options``include_search_results` をサポートします。
- `WebSearchTool` は、`filters``user_location``search_context_size` をサポートします。
@@ -60,11 +60,11 @@ async def main():
print(result.final_output)
```
### Hosted tool search
### ホスト型ツール検索
ツール検索により、 OpenAI Responses モデルは大規模なツール面を実行時まで遅延できるため、モデルは現在のターンに必要なサブセットだけを読み込みます。これは、多数の関数ツール、名前空間グループ、またはホスト MCP サーバーがあり、すべてのツールを事前公開せずにツールスキーマのトークンを削減したい場合に有用です。
ツール検索を使用すると、OpenAI Responses モデルは大規模なツール群の読み込みをランタイムまで延期できるため、現在のターンに必要なサブセットのみをモデルが読み込みます。多数の関数ツール、名前空間グループ、またはホスト MCP サーバーがあり、すべてのツールを事前公開せずにツールスキーマのトークンを削減したい場合に便利です。
候補ツールがエージェント構築時に既知である場合は、 hosted tool search から開始してください。アプリケーションが動的に読み込む対象を判断する必要がある場合、 Responses API はクライアント実行のツール検索もサポートしますが、標準の `Runner` はそのモードを自動実行しません。
エージェント構築する時点で候補ツールがすでに判明している場合は、ホスト型ツール検索から始めてください。アプリケーション側で読み込む内容を動的に決定する必要がある場合、Responses API はクライアント実行のツール検索もサポートしていますが、標準の `Runner` はそのモードを自動実行しません。
```python
from typing import Annotated
@@ -97,7 +97,7 @@ crm_tools = tool_namespace(
agent = Agent(
name="Operations assistant",
model="gpt-5.4",
model="gpt-5.6-sol",
instructions="Load the crm namespace before using CRM tools.",
tools=[*crm_tools, ToolSearchTool()],
)
@@ -106,26 +106,26 @@ result = await Runner.run(agent, "Look up customer_42 and list their open orders
print(result.final_output)
```
知っておくべき点:
注意事項:
- Hosted tool search は OpenAI Responses モデルでのみ利用可能です。現在の Python SDK サポートは `openai>=2.25.0` に依存します。
- エージェント遅延読み込みを設定する場合は、`ToolSearchTool()`正確に 1 つ追加してください。
- 検索可能なには、`@function_tool(defer_loading=True)``tool_namespace(name=..., description=..., tools=[...])``HostedMCPTool(tool_config={..., "defer_loading": True})` が含まれます。
- 遅延読み込み関数ツールは `ToolSearchTool()` と組み合わせる必要があります。名前空間のみの構成でも、モデルが必要時に適切なグループを読み込めるよう `ToolSearchTool()` を使用できます。
- `tool_namespace()` は、`FunctionTool` インスタンスを共有の名前空間名と説明の下にグループ化します。これは通常、`crm``billing``shipping` のように関連ツールが多場合に最適です。
- OpenAI の公式ベストプラクティスガイドは [Use namespaces where possible](https://developers.openai.com/api/docs/guides/tools-tool-search#use-namespaces-where-possible) です。
- 可能な場合は、多数の個別遅延関数よりも名前空間またはホスト MCP サーバーを優先してください。通常、モデルにとってより良い高レベル検索面と、より高いトークン削減効果が得られます。
- 名前空間には即時ツールと遅延ツールを混在できます。`defer_loading=True` がないツールは即呼び出し可能なままで、同じ名前空間内の遅延ツールはツール検索経由で読み込まれます。
- 目安として、各名前空間は比較的小さく保ち、理想的には 10 関数未満にしてください
- 名前付き `tool_choice` は、の名前空間名や遅延専用ツールを対象にできません。`auto``required`、または実在するトップレベル呼び出し可能ツール名を優先してください。
- `ToolSearchTool(execution="client")`手動 Responses オーケストレーションです。モデルがクライアント実行の `tool_search_call` を出力した場合、標準 `Runner`あなたの代わりに実行せずエラーにします。
- ツール検索アクティビティは [`RunResult.new_items`](results.md#new-items) と、専用のアイテム / イベント型を持つ [`RunItemStreamEvent`](streaming.md#run-item-event-names) に表示されます。
- 名前空間読み込みとトップレベル遅延ツールの両方を網羅した実行可能な完全例は `examples/tools/tool_search.py` を参照してください。
- 公式プラットフォームガイド: [Tool search](https://developers.openai.com/api/docs/guides/tools-tool-search)。
- ホスト型ツール検索は、OpenAI Responses モデルでのみ利用できます。現在の Python SDK サポートは `openai>=2.25.0` に依存します。
- エージェント遅延読み込み対象を設定する場合は、`ToolSearchTool()` を 1 つだけ追加してください。
- 検索可能な対象には、`@function_tool(defer_loading=True)``tool_namespace(name=..., description=..., tools=[...])``HostedMCPTool(tool_config={..., "defer_loading": True})` が含まれます。
- 遅延読み込みされる関数ツールは`ToolSearchTool()` と組み合わせる必要があります。名前空間のみの構成でも `ToolSearchTool()` を使用すると、モデルが適切なグループをオンデマンドで読み込めます。
- `tool_namespace()` は、共有の名前空間名と説明の下に `FunctionTool` インスタンスをまとめます。通常、`crm``billing``shipping` など、関連するツールが多数ある場合に最適です。
- OpenAI の公式ベストプラクティスガイダンスは、[可能な限り名前空間を使用する](https://developers.openai.com/api/docs/guides/tools-tool-search#use-namespaces-where-possible)ことです。
- 可能であれば、個別遅延読み込みされる関数を多数使用するのではなく、名前空間またはホスト MCP サーバーを優先してください。通常、その方がモデルにとって優れた高レベル検索対象となり、トークンをより効果的に節約できます。
- 名前空間では、即時利用可能なツールと遅延読み込みされるツールを混在させられます。`defer_loading=True`指定されていないツールは即座に呼び出し可能なままであり、同じ名前空間内の遅延ツールはツール検索を通じて読み込まれます。
- 目安として、各名前空間は比較的小さく保ち、関数を 10 未満にすることが理想的です
- 名前付き `tool_choice` は、単独の名前空間名や遅延読み込み専用ツールを対象にできません。`auto``required`、または実際にトップレベル呼び出し可能ツール名を使用してください。
- `ToolSearchTool(execution="client")`Responses を手動でオーケストレーションするためのものです。モデルがクライアント実行`tool_search_call` を出力した場合、標準 `Runner`それを実行せずに例外を発生させます。
- ツール検索アクティビティは、専用の項目型およびイベント型として [`RunResult.new_items`](results.md#new-items) と [`RunItemStreamEvent`](streaming.md#run-item-event-names) に表示されます。
- 名前空間による読み込みとトップレベル遅延ツールの両方を扱う、実行可能な完全なコード例については、`examples/tools/tool_search.py` を参照してください。
- 公式プラットフォームガイド[ツール検索](https://developers.openai.com/api/docs/guides/tools-tool-search)。
### ホストコンテナ shell + skills
### ホストコンテナシェルとスキル
`ShellTool` OpenAI ホストコンテナ実行もサポートします。モデルにローカルランタイムではなく管理コンテナで shell コマンドを実行させたい場合は、このモードを使用してください。
`ShellTool`OpenAI ホストするコンテナでの実行もサポートしています。ローカルランタイムではなく管理されたコンテナ内でモデルにシェルコマンドを実行させたい場合は、このモードを使用してください。
```python
from agents import Agent, Runner, ShellTool, ShellToolSkillReference
@@ -138,7 +138,7 @@ csv_skill: ShellToolSkillReference = {
agent = Agent(
name="Container shell agent",
model="gpt-5.4",
model="gpt-5.6-sol",
instructions="Use the mounted skill when helpful.",
tools=[
ShellTool(
@@ -158,52 +158,52 @@ result = await Runner.run(
print(result.final_output)
```
後続の run で既存コンテナを再利用するには、`environment={"type": "container_reference", "container_id": "cntr_..."}` を設定します。
後続の実行で既存コンテナを再利用するには、`environment={"type": "container_reference", "container_id": "cntr_..."}` を設定します。
知っておくべき点:
注意事項:
- ホスト shell は Responses API の shell ツール経由で利用可能です。
- `container_auto` はリクエスト用コンテナをプロビジョニングし、`container_reference` は既存コンテナを再利用します。
- `container_auto` には `file_ids``memory_limit`含められます。
- `environment.skills` skill 参照とインライン skill バンドルを受け付けます。
- ホスト環境では、`ShellTool``executor``needs_approval``on_approval` を設定しないでください。
- `network_policy` `disabled``allowlist` モードをサポートします。
- allowlist モードでは、`network_policy.domain_secrets` ドメインスコープシークレットを名前で注入できます。
- 完全な例は `examples/tools/container_shell_skill_reference.py``examples/tools/container_shell_inline_skill.py` を参照してください。
- OpenAI プラットフォームガイド: [Shell](https://platform.openai.com/docs/guides/tools-shell) と [Skills](https://platform.openai.com/docs/guides/tools-skills)。
- ホスト型シェルは、Responses API のシェルツールを通じて利用できます。
- `container_auto` はリクエスト用コンテナをプロビジョニングし、`container_reference` は既存コンテナを再利用します。
- `container_auto` には`file_ids``memory_limit`指定できます。
- `environment.skills`、スキル参照およびインラインスキルバンドルを受け付けます。
- ホスト環境では、`ShellTool``executor``needs_approval``on_approval` を設定しないでください。
- `network_policy``disabled` モード`allowlist` モードをサポートします。
- 許可リストモードでは、`network_policy.domain_secrets` を使用して、ドメインスコープされたシークレットを名前で注入できます。
- 完全なコード例については、`examples/tools/container_shell_skill_reference.py``examples/tools/container_shell_inline_skill.py` を参照してください。
- OpenAI プラットフォームガイド[シェル](https://platform.openai.com/docs/guides/tools-shell)および[スキル](https://platform.openai.com/docs/guides/tools-skills)。
## ローカルランタイムツール
ローカルランタイムツールは、モデル応答自体の外で実行されます。モデルはいつ呼び出すかを決定しますが、実際の処理はアプリケーションまたは設定済み実行環境が行います。
ローカルランタイムツールは、モデルのレスポンス自体の外で実行されます。モデルは引き続き呼び出すタイミングを決定しますが、実際の処理はアプリケーションまたは設定された実行環境が行います。
`ComputerTool``ApplyPatchTool` は常に、あなたが提供するローカル実装を必要とします。`ShellTool` は両モードにまたがります。管理実行が必要な上記ホストコンテナ構成を使い、自分のプロセスでコマンドを実行したいなら以下のローカルランタイム構成を使ってください。
`ComputerTool``ApplyPatchTool` には、ユーザーが提供するローカル実装が常に必要です。`ShellTool` は両方のモードに対応しています。管理された実行が必要な場合は上記ホストコンテナ設定を使用し、独自のプロセスでコマンドを実行する場合は以下のローカルランタイム設定を使用してください。
ローカルランタイムツールでは実装提供が必要です:
ローカルランタイムツールを使用するには、実装提供する必要があります。
- [`ComputerTool`][agents.tool.ComputerTool]: GUI / ブラウザ自動化を有効にするには [`Computer`][agents.computer.Computer] または [`AsyncComputer`][agents.computer.AsyncComputer] インターフェースを実装します。
- [`ShellTool`][agents.tool.ShellTool]: ローカル実行とホストコンテナ実行の両方に対応する最新 shell ツールです。
- [`LocalShellTool`][agents.tool.LocalShellTool]: レガシーのローカル shell 統合です。
- [`ApplyPatchTool`][agents.tool.ApplyPatchTool]: 差分をローカル適用するには [`ApplyPatchEditor`][agents.editor.ApplyPatchEditor] を実装します。
- ローカル shell skills は `ShellTool(environment={"type": "local", "skills": [...]})` 利用できます。
- [`ComputerTool`][agents.tool.ComputerTool]GUIブラウザーの自動化を有効にするには[`Computer`][agents.computer.Computer] または [`AsyncComputer`][agents.computer.AsyncComputer] インターフェースを実装します。
- [`ShellTool`][agents.tool.ShellTool]ローカル実行とホストコンテナ実行の両方に対応する最新のシェルツールです。
- [`LocalShellTool`][agents.tool.LocalShellTool]:従来のローカルシェル統合です。
- [`ApplyPatchTool`][agents.tool.ApplyPatchTool]差分をローカル適用するには[`ApplyPatchEditor`][agents.editor.ApplyPatchEditor] を実装します。
- `ShellTool(environment={"type": "local", "skills": [...]})` を使用すると、ローカルシェルスキルを利用できます。
### ComputerTool と Responses computer tool
### ComputerTool と Responses のコンピュータツール
`ComputerTool`依然としてローカルハーネスです。あなたが [`Computer`][agents.computer.Computer] または [`AsyncComputer`][agents.computer.AsyncComputer] 実装を提供し、 SDK がそのハーネスを OpenAI Responses API の computer 面にマッピングします。
`ComputerTool`引き続きローカルハーネスです。[`Computer`][agents.computer.Computer] または [`AsyncComputer`][agents.computer.AsyncComputer] 実装を提供すると、SDK がそのハーネスを OpenAI Responses API のコンピュータ機能にマッピングします。
明示的な [`gpt-5.4`](https://developers.openai.com/api/docs/models/gpt-5.4) リクエストでは、 SDK は GA 組み込みツールペイロード `{"type": "computer"}` を送信します。古い `computer-use-preview` モデルでは、プレビューペイロード `{"type": "computer_use_preview", "environment": ..., "display_width": ..., "display_height": ...}` を維持します。これは OpenAI の [Computer use guide](https://developers.openai.com/api/docs/guides/tools-computer-use/) で説明されているプラットフォーム移行を反映しています。
明示的な [`gpt-5.5`](https://developers.openai.com/api/docs/models/gpt-5.5) リクエストでは、SDK は GA 組み込みツールペイロード `{"type": "computer"}` を送信します。以前の `computer-use-preview` モデルでは、プレビューペイロード `{"type": "computer_use_preview", "environment": ..., "display_width": ..., "display_height": ...}` が引き続き使用されます。これはOpenAI の[コンピュータ操作ガイド](https://developers.openai.com/api/docs/guides/tools-computer-use/)で説明されているプラットフォーム移行に対応しています。
- モデル: `computer-use-preview` -> `gpt-5.4`
- ツールセレクター: `computer_use_preview` -> `computer`
- Computer 呼び出し形状: `computer_call` あたり 1 つの `action` -> `computer_call` 上のバッチ `actions[]`
- Truncation: プレビューパスでは `ModelSettings(truncation="auto")` が必須 -> GA パスでは不要
- モデル`computer-use-preview` -> `gpt-5.5`
- ツールセレクター`computer_use_preview` -> `computer`
- コンピュータ呼び出しの形式:`computer_call` ごとに 1 つの `action` -> `computer_call` 上の一括 `actions[]`
- 切り詰め:プレビューパスでは `ModelSettings(truncation="auto")` が必須 -> GA パスでは不要
SDK は、実際の Responses リクエスト上の有効モデルから wire 形状を選択します。プロンプトテンプレートを使い、プロンプト側が `model` を所有するためリクエスト `model`ない場合、`model="gpt-5.4"` を明示するか、`ModelSettings(tool_choice="computer")` または `ModelSettings(tool_choice="computer_use")` で GA セレクターを強制しない限り、 SDK はプレビュー互換 computer ペイロードを維持します。
SDK は、実際の Responses リクエスト有効モデルに基づいて、そのワイヤ形式を選択します。プロンプトテンプレートを使用しており、モデルがプロンプト側で指定されているためリクエスト `model`省略される場合、`model="gpt-5.5"` を明示したままにするか、`ModelSettings(tool_choice="computer")` または `ModelSettings(tool_choice="computer_use")` で GA セレクターを強制しない限り、SDK はプレビュー互換のコンピュータペイロードを維持します。
[`ComputerTool`][agents.tool.ComputerTool] が存在する場合、`tool_choice="computer"``"computer_use"``"computer_use_preview"` はすべて受け入れられ、有効リクエストモデルに一致する組み込みセレクターへ正規化されます。`ComputerTool` がない場合、これらの文字列は通常の関数名として動作します。
[`ComputerTool`][agents.tool.ComputerTool] が存在する場合、`tool_choice="computer"``"computer_use"``"computer_use_preview"` はすべて受け付けられ、有効リクエストモデルに一致する組み込みセレクターへ正規化されます。`ComputerTool` がない場合、これらの文字列は通常の関数名として動作します。
この違いは、`ComputerTool` が [`ComputerProvider`][agents.tool.ComputerProvider] ファクトリーに支えられている場合に重要です。GA の `computer` ペイロードシリアライズ時に `environment`寸法を必要としないため、未解決ファクトリーでも問題ありません。プレビュー互換シリアライズでは、 SDK が `environment``display_width``display_height` を送るため、解決済みの `Computer` または `AsyncComputer` インスタンスが依然必要です。
`ComputerTool` が [`ComputerProvider`][agents.tool.ComputerProvider] ファクトリーによって提供される場合、この違いは重要です。GA の `computer` ペイロードでは、シリアライズ時に `environment`表示サイズが不要なため、未解決ファクトリーでも問題ありません。一方、プレビュー互換シリアライズでは、SDK が `environment``display_width``display_height` を送信できるよう、解決済みの `Computer` または `AsyncComputer` インスタンスが必要です。
実行時は、どちらのパスも同じローカルハーネスを使ます。プレビュー応答は単一 `action` `computer_call` アイテムを出力し`gpt-5.4`バッチ `actions[]` を出力でき、 SDK は `computer_call_output` スクリーンショットアイテムを生成する前に順番に実行します。実行可能な Playwright ベースのハーネスは `examples/tools/computer_use.py` を参照してください。
ランタイムでは、どちらのパスも同じローカルハーネスを使用します。プレビューのレスポンスは、単一 `action` を持つ `computer_call` 項目を出力します。`gpt-5.5`一括の `actions[]` を出力でき、SDK は `computer_call_output` スクリーンショット項目を生成する前に、それらを順番に実行します。Playwright ベースの実行可能なハーネスについては、`examples/tools/computer_use.py` を参照してください。
```python
from agents import Agent, ApplyPatchTool, ShellTool
@@ -247,16 +247,16 @@ agent = Agent(
## 関数ツール
任意の Python 関数をツールとして使ます。 Agents SDK が自動的にツールを設定します。
任意の Python 関数をツールとして使用できます。Agents SDK がツールを自動的にセットアップします。
- ツール名は Python 関数名になります (または名前を提供できます)
- ツール説明は関数の docstring から取得されます (または説明を提供できます)
- 関数入力のスキーマは、関数引数から自動成されます
- 各入力の説明は、無効しない限り関数の docstring から取得されます
- ツール名は Python 関数の名前が使用されます(または名前を指定できます
- ツール説明は関数の docstring が使用されますまたは説明を指定できます
- 関数入力のスキーマは、関数引数から自動的に作成されます
- 無効しない限り、各入力の説明は関数の docstring から取得されます
関数シグネチャ抽出には Python の `inspect` モジュールを使用し、docstring 解析には [`griffe`](https://mkdocstrings.github.io/griffe/)、スキーマ作成には `pydantic` を使用します。
Python の `inspect` モジュールを使用して関数シグネチャを抽出し、[`griffe`](https://mkdocstrings.github.io/griffe/) で docstring を解析し、`pydantic` でスキーマを作成します。
OpenAI Responses モデルを使用している場合、`@function_tool(defer_loading=True)` `ToolSearchTool()` が読み込むまで関数ツールを非表示にします。[`tool_namespace()`][agents.tool.tool_namespace] で関連関数ツールをグループ化することもできます。完全な設定と制約は [Hosted tool search](#hosted-tool-search) を参照してください。
OpenAI Responses モデルを使用している場合、`@function_tool(defer_loading=True)``ToolSearchTool()` が読み込むまで関数ツールを非表示にします。[`tool_namespace()`][agents.tool.tool_namespace] を使用して、関連する関数ツールをグループ化することもできます。完全な設定と制約については、[ホスト型ツール検索](#hosted-tool-search)を参照してください。
```python
import json
@@ -308,12 +308,12 @@ for tool in agent.tools:
```
1. 関数引数には任意の Python 型を使用でき、関数は sync / async どちらでも構いません
2. docstring がる場合、説明引数説明取得に使用されます
3. 関数は任意で `context` を受け取れます (最初の引数である必要があります)。ツール名、説明、使用する docstring スタイルなどオーバーライドも設定できます。
4. デコレートした関数をツールリストに渡せます。
1. 関数引数には任意の Python 型を使用でき、関数は同期または非同期にできます
2. docstring が存在する場合、説明および引数説明取得するために使用されます
3. 関数は必要に応じて `context` を受け取れます最初の引数である必要があります。ツール名、説明、使用する docstring スタイルなどオーバーライドすることもできます。
4. デコレートした関数をツールリストに渡せます。
??? note "出力表示"
??? note "出力の展開表示"
```
fetch_weather
@@ -385,20 +385,20 @@ for tool in agent.tools:
### 関数ツールからの画像またはファイルの返却
テキスト出力の返却に加えて、関数ツールの出力として 1 つ以上の画像またはファイルを返せます。そのためには、次のいずれかを返します。
テキスト出力に加えて、1 つまたは複数の画像やファイルを関数ツールの出力として返せます。そのためには、次のいずれかを返します。
- 画像: [`ToolOutputImage`][agents.tool.ToolOutputImage] (または TypedDict 版の [`ToolOutputImageDict`][agents.tool.ToolOutputImageDict])
- ファイル: [`ToolOutputFileContent`][agents.tool.ToolOutputFileContent] (または TypedDict 版の [`ToolOutputFileContentDict`][agents.tool.ToolOutputFileContentDict])
- テキスト: 文字列、文字列化可能オブジェクト、または [`ToolOutputText`][agents.tool.ToolOutputText] (または TypedDict 版の [`ToolOutputTextDict`][agents.tool.ToolOutputTextDict])
- 画像[`ToolOutputImage`][agents.tool.ToolOutputImage]または TypedDict 版の [`ToolOutputImageDict`][agents.tool.ToolOutputImageDict]
- ファイル[`ToolOutputFileContent`][agents.tool.ToolOutputFileContent]または TypedDict 版の [`ToolOutputFileContentDict`][agents.tool.ToolOutputFileContentDict]
- テキスト文字列、文字列化可能オブジェクト、または [`ToolOutputText`][agents.tool.ToolOutputText]または TypedDict 版の [`ToolOutputTextDict`][agents.tool.ToolOutputTextDict]
### カスタム関数ツール
場合によっては、 Python 関数をツールとして使たくないことがあります。その場合は、必要に応じて [`FunctionTool`][agents.tool.FunctionTool] を直接作成できます。必要なものは次のとおりです。
Python 関数をツールとして使用したくない場合もあります。必要に応じて[`FunctionTool`][agents.tool.FunctionTool] を直接作成できます。次の項目を指定する必要があります。
- `name`
- `description`
- `params_json_schema` (引数の JSON スキーマ)
- `on_invoke_tool` ( [`ToolContext`][agents.tool_context.ToolContext] と JSON 文字列としての引数を受け取り、ツール出力 (たとえばテキスト、構造化ツール出力オブジェクト、または出力リスト) を返す async 関数)
- `params_json_schema`引数の JSON スキーマ
- `on_invoke_tool`[ツールコンテキスト][agents.tool_context.ToolContext]と JSON 文字列形式の引数を受け取り、ツール出力テキスト、構造化されたツール出力オブジェクト、出力リストなど)を返す非同期関数
```python
from typing import Any
@@ -433,16 +433,16 @@ tool = FunctionTool(
### 引数と docstring の自動解析
前述のとおり、ツール用スキーマ抽出のために関数シグネチャを自動解析しツール説明と個別引数説明抽出のために docstring を解析します。注意点は次のとおりです。
前述のように、関数シグネチャを自動的に解析しツールのスキーマを抽出し、docstring を解析してツールおよび個々の引数の説明を抽出します。これに関する注意事項は次のとおりです。
1. シグネチャ解析は `inspect` モジュールで行います。引数型の理解には型アノテーションを使い、全体スキーマを表す Pydantic モデルを動的に構築します。 Python プリミティブ、Pydantic モデル、TypedDict などを含む、ほとんどの型をサポートします。
2. docstring 解析には `griffe` を使用します。サポートされる docstring 形式は `google`、`sphinx`、`numpy` です。docstring 形式自動検出を試みますが、これはベストエフォートであり、`function_tool` 呼び出し時に明示設定できます。`use_docstring_info` を `False` に設定して docstring 解析を無効することもできます。
1. シグネチャ解析は `inspect` モジュールを使用して行われます。型アノテーションを使用して引数の型を把握し、スキーマ全体を表す Pydantic モデルを動的に構築します。Python の基本型、Pydantic モデル、TypedDict など、ほとんどの型をサポートしています。
2. docstring 解析には `griffe` を使用します。サポートされる docstring 形式は `google`、`sphinx`、`numpy` です。docstring 形式自動検出を試みますが、これはベストエフォートであり、`function_tool` 呼び出し時に明示的に設定できます。`use_docstring_info` を `False` に設定してdocstring 解析を無効することもできます。
スキーマ抽出コードは [`agents.function_schema`][] にあります。
スキーマ抽出コードは [`agents.function_schema`][] にあります。
### Pydantic Field による引数制約と説明
### Pydantic Field による引数制約と説明
Pydantic の [`Field`](https://docs.pydantic.dev/latest/concepts/fields/) を使うと、ツール引数に制約 (例: 数値の最小 / 最大、文字列の長さやパターン) と説明を追加できます。Pydantic と同様に、デフォルトベース (`arg: int = Field(..., ge=1)`) と `Annotated` (`arg: Annotated[int, Field(..., ge=1)]`) の両形式をサポートます。生成される JSON スキーマとバリデーションには、これらの制約が含まれます。
Pydantic の [`Field`](https://docs.pydantic.dev/latest/concepts/fields/) を使用して、ツール引数に制約数値の最小値/最大、文字列の長さやパターンなど)と説明を追加できます。Pydantic と同様に、デフォルトベースの形式(`arg: int = Field(..., ge=1)`と `Annotated` 形式(`arg: Annotated[int, Field(..., ge=1)]`)の両方がサポートされます。生成される JSON スキーマとバリデーションには、これらの制約が含まれます。
```python
from typing import Annotated
@@ -462,7 +462,7 @@ def score_b(score: Annotated[int, Field(..., ge=0, le=100, description="Score fr
### 関数ツールのタイムアウト
async 関数ツールには、`@function_tool(timeout=...)` 呼び出しごとタイムアウトを設定できます。
`@function_tool(timeout=...)` を使用して、非同期関数ツールの呼び出しごとタイムアウトを設定できます。
```python
import asyncio
@@ -482,13 +482,13 @@ agent = Agent(
)
```
タイムアウトに達した場合、デフォルト動作は `timeout_behavior="error_as_result"` で、モデル可視のタイムアウトメッセージ (例: `Tool 'slow_lookup' timed out after 2 seconds.`) を送信します。
タイムアウトに達した場合、デフォルト動作は `timeout_behavior="error_as_result"` で、モデルから確認できるタイムアウトメッセージ(例:`Tool 'slow_lookup' timed out after 2 seconds.`を送信します。
タイムアウト処理は次のように制御できます。
- `timeout_behavior="error_as_result"` (デフォルト): タイムアウトメッセージをモデルに返し、復旧できるようにします。
- `timeout_behavior="raise_exception"`: [`ToolTimeoutError`][agents.exceptions.ToolTimeoutError] を発生させ、 run を失敗させます。
- `timeout_error_function=...`: `error_as_result` 使用のタイムアウトメッセージをカスタマイズします。
- `timeout_behavior="error_as_result"`デフォルト):モデルが復旧できるよう、タイムアウトメッセージをモデルに返します。
- `timeout_behavior="raise_exception"`[`ToolTimeoutError`][agents.exceptions.ToolTimeoutError] を発生させ、実行を失敗させます。
- `timeout_error_function=...``error_as_result` 使用する場合のタイムアウトメッセージをカスタマイズします。
```python
import asyncio
@@ -511,15 +511,15 @@ except ToolTimeoutError as e:
!!! note
タイムアウト設定は async `@function_tool` ハンドラーでのみサポートされます。
タイムアウト設定は、非同期の `@function_tool` ハンドラーでのみサポートされます。
### 関数ツールでのエラー処理
`@function_tool` 関数ツールを作成する、`failure_error_function` を渡せます。これは、ツール呼び出しがクラッシュしたときに LLM へ返すエラー応答を提供する関数です。
`@function_tool` を使用して関数ツールを作成する場合、`failure_error_function` を渡せます。これは、ツール呼び出しがクラッシュした場合に LLM へエラーレスポンスを提供する関数です。
- デフォルト (何も渡さない場合) では、エラー発生を LLM に伝える `default_tool_error_function` が実行されます。
- 独自のエラー関数を渡すと、代わりにそが実行され、その応答が LLM に送れます。
- 明示的に `None` を渡すと、ツール呼び出しエラーはあなたが処理できるよう再送出されます。これはモデルが無効 JSON を生成した場合 `ModelBehaviorError`、コードがクラッシュした場合 `UserError` などです。
- デフォルトでは(何も渡さない場合、エラー発生したことを LLM に通知する `default_tool_error_function` が実行されます。
- 独自のエラー関数を渡した場合は、代わりにその関数が実行され、レスポンスが LLM に送信されます。
- 明示的に `None` を渡した場合、ツール呼び出しエラーは再度発生し、ユーザー側で処理できます。モデルが無効 JSON を生成した場合 `ModelBehaviorError`、コードがクラッシュした場合 `UserError` になる可能性があります。
```python
from agents import function_tool, RunContextWrapper
@@ -542,11 +542,11 @@ def get_user_profile(user_id: str) -> str:
```
`FunctionTool` オブジェクトを手動作成する場合、`on_invoke_tool` 関数内でエラーを処理する必要があります。
`FunctionTool` オブジェクトを手動作成する場合、`on_invoke_tool` 関数内でエラーを処理する必要があります。
## Agents as tools
一部のワークフローは、制御をハンドオフする代わりに、中央エージェントで専門エージェントのネットワークをエージェントオーケストレーションしたい場合があります。これは、エージェントをツールとしてモデル化することで実現できます。
ワークフローによっては、制御をハンドオフする代わりに、中央エージェントで特化型エージェントのネットワークをオーケストレーションしたい場合があります。これは、エージェントをツールとしてモデル化することで実現できます。
```python
from agents import Agent, Runner
@@ -565,7 +565,7 @@ french_agent = Agent(
orchestrator_agent = Agent(
name="orchestrator_agent",
instructions=(
"You are a translation agent. You use the tools given to you to translate."
"You are a translation agent. You use the tools given to you to translate. "
"If asked for multiple translations, you call the relevant tools."
),
tools=[
@@ -587,7 +587,9 @@ async def main():
### ツールエージェントのカスタマイズ
`agent.as_tool` 関数は、エージェントをツール変換しやすくするための便利メソッドです。`max_turns`、`run_config`、`hooks`、`previous_response_id`、`conversation_id`、`session`、`needs_approval` など一般的なランタイムオプションをサポートします。さらに、`parameters`、`input_builder`、`include_input_schema` による構造化入力もサポートします。高度なオーケストレーション (例: 条件付きリトライ、フォールバック動作、複数エージェント呼び出しの連鎖) では、ツール実装内で `Runner.run` を直接使用してください。
`agent.as_tool` 関数は、エージェントを簡単にツール変換するための便利メソッドです。`max_turns`、`run_config`、`hooks`、`previous_response_id`、`conversation_id`、`session`、`needs_approval` など一般的なランタイムオプションをサポートします。また、`parameters`、`input_builder`、`include_input_schema` による構造化入力もサポートします。
状態オプションは、ツール呼び出しによって開始されるネストされたエージェント実行を設定します。親実行の会話状態は自動的には継承されません。クライアント管理の履歴を親実行とネストされた実行の間で共有するには、同じ `session` を両方に明示的に渡してください。`Runner.run` と同様に、ネストされた実行には 1 つの状態戦略を選択してください。クライアント管理の `session`、または `previous_response_id` や `conversation_id` を使用したサーバー管理の継続のいずれかです。
```python
@function_tool
@@ -608,13 +610,13 @@ async def run_my_agent() -> str:
### ツールエージェントの構造化入力
デフォルトでは、`Agent.as_tool()` は単一文字列入力 (`{"input": "..."}`) を想定しますが、`parameters` (Pydantic モデルまたは dataclass 型) を渡すことで構造化スキーマを公開できます。
デフォルトでは、`Agent.as_tool()` は単一文字列入力`{"input": "..."}`を想定しますが、`parameters`Pydantic モデルまたは dataclass 型を渡すことで構造化スキーマを公開できます。
追加オプション:
追加オプション
- `include_input_schema=True` 、生成されるネスト入力に完全な JSON Schema を含めます。
- `input_builder=...` 、構造化ツール引数をネストエージェント入力変換する方法を完全にカスタマイズできます。
- `RunContextWrapper.tool_input` は、ネスト run コンテキスト内解析済み構造化ペイロードを保持します。
- `include_input_schema=True` を指定すると、生成されるネストされた入力に完全な JSON Schema が含まれます。
- `input_builder=...` を使用すると、構造化されたツール引数をネストされたエージェント入力変換する方法を完全にカスタマイズできます。
- `RunContextWrapper.tool_input` は、ネストされた実行コンテキスト内解析済み構造化ペイロードが格納されます。
```python
from pydantic import BaseModel, Field
@@ -634,21 +636,21 @@ translator_tool = translator_agent.as_tool(
)
```
完全に実行可能な例は `examples/agent_patterns/agents_as_tools_structured.py` を参照してください。
実行可能な完全なコード例については、`examples/agent_patterns/agents_as_tools_structured.py` を参照してください。
### ツールエージェントの承認ゲート
`Agent.as_tool(..., needs_approval=...)` は `function_tool` と同じ承認フローを使用します。承認が必要な場合、 run は一時停止し、保留中アイテムは `result.interruptions` に表示されます。次に `result.to_state()` を使用し、`state.approve(...)` または `state.reject(...)` 呼び出し後に再開します。完全な一時停止 / 再開パターン[Human-in-the-loop guide](human_in_the_loop.md) を参照してください。
`Agent.as_tool(..., needs_approval=...)` は`function_tool` と同じ承認フローを使用します。承認が必要な場合、実行は一時停止し、保留中の項目が `result.interruptions` に表示されます。次に `result.to_state()` を使用し、`state.approve(...)` または `state.reject(...)` 呼び出し後に再開します。完全な一時停止再開パターンについては、[Human-in-the-loop ガイド](human_in_the_loop.md)を参照してください。
### カスタム出力抽出
### カスタム出力抽出
特定のケースでは、中央エージェントに返す前にツールエージェントの出力を変更したいことがあります。これは次のような場合に有用です。
場合によっては、中央エージェントに返す前にツールエージェントの出力を変更したいことがあります。これは次のような場合に役立ちます。
- サブエージェントのチャット履歴から特定情報 (例: JSON ペイロード) を抽出する。
- エージェントの最終回答を変換または再整形する (例: Markdown をプレーンテキストや CSV に変換)
- 出力を検証するまたはエージェント応答が欠落 / 不正形式の場合にフォールバック値を提供する。
- サブエージェントのチャット履歴から特定情報JSON ペイロードなど)を抽出する。
- エージェントの最終回答を変換または再フォーマットする(Markdown をプレーンテキストや CSV に変換するなど)
- 出力を検証するまたはエージェントのレスポンスが欠落しているか不正形式の場合にフォールバック値を提供する。
これは、`as_tool` メソッドに `custom_output_extractor` 引数を渡すことで実現できます。
これは、`as_tool` メソッドに `custom_output_extractor` 引数を指定することで実現できます。
```python
async def extract_json_payload(run_result: RunResult) -> str:
@@ -667,14 +669,11 @@ json_tool = data_agent.as_tool(
)
```
カスタム抽出内では、ネストされた [`RunResult`][agents.result.RunResult]
[`agent_tool_invocation`][agents.result.RunResultBase.agent_tool_invocation] も公開します。これは
ネスト結果の後処理中に、外側ツール名、呼び出し ID、または raw 引数が必要な場合に有用です。
[Results guide](results.md#agent-as-tool-metadata) も参照してください。
カスタム抽出関数内では、ネストされた [`RunResult`][agents.result.RunResult] から [`agent_tool_invocation`][agents.result.RunResultBase.agent_tool_invocation] にもアクセスできます。これは、ネストされた実行結果を後処理する際に、外側のツール名、呼び出し ID、または raw 引数が必要な場合に便利です。[実行結果ガイド](results.md#agent-as-tool-metadata)を参照してください。
### ネストされたエージェント run のストリーミング
### ネストされたエージェント実行のストリーミング
`as_tool` に `on_stream` コールバックを渡すと、ストリーム完了後に最終出力を返しつつ、ネストエージェントが出力するストリーミングイベントを監視できます。
`as_tool` に `on_stream` コールバックを渡すと、ネストされたエージェントが出力するストリーミングイベントを受け取りながら、ストリームの完了後に最終出力を返せます。
```python
from agents import AgentToolStreamEvent
@@ -692,17 +691,17 @@ billing_agent_tool = billing_agent.as_tool(
)
```
想定される挙動:
想定される動作:
- イベント型は `StreamEvent["type"]` を反映します: `raw_response_event`、`run_item_stream_event`、`agent_updated_stream_event`。
- `on_stream` を提供すると、ネストエージェントは自動的にストリーミングモードで実行され、最終出力返却前にストリームがドレインされます。
- ハンドラーは同期または非同期にでき各イベントは到着順で配信されます。
- `tool_call` は、モデルのツール呼び出し経由でツールが呼れた場合存在します。直接呼び出しは `None` のままの場合があります。
- 完全に実行可能なサンプル`examples/agent_patterns/agents_as_tools_streaming.py` を参照してください。
- イベント型は `StreamEvent["type"]` と同様です:`raw_response_event`、`run_item_stream_event`、`agent_updated_stream_event`。
- `on_stream` を指定すると、ネストされたエージェントは自動的にストリーミングモードで実行され、最終出力を返す前にストリームが最後まで処理されます。
- ハンドラーは同期または非同期にできます。各イベントは到着した順に渡されます。
- モデルのツール呼び出し経由でツールが呼び出された場合、`tool_call` が存在します。直接呼び出した場合は `None` になることがあります。
- 実行可能な完全なサンプルについては、`examples/agent_patterns/agents_as_tools_streaming.py` を参照してください。
### 条件付きツール有効化
`is_enabled` パラメーターを使うと、実行時にエージェントツールを条件付きで有効 / 無効にできます。これにより、コンテキスト、ユーザー設定、またはランタイム条件に基づいて、 LLM が利用可能なツールを動的にフィルタリングできます。
`is_enabled` パラメーターを使用して、ランタイムでエージェントツールを条件付きで有効または無効にできます。これにより、コンテキスト、ユーザー設定、ランタイム条件に基づいて、LLM が利用できるツールを動的にフィルタリングできます。
```python
import asyncio
@@ -757,24 +756,24 @@ async def main():
asyncio.run(main())
```
`is_enabled` パラメーターはを受け付けます。
`is_enabled` パラメーターは、次の値を受け付けます。
- **ブール値**: `True` (常に有効) または `False` (常に無効)
- **呼び出し可能関数**: `(context, agent)` を受け取りブール値を返す関数
- **非同期関数**: 複雑な条件ロジック向けの async 関数
- **ブール値**`True`常に有効または `False`常に無効
- **呼び出し可能関数**`(context, agent)` を受け取りブール値を返す関数
- **非同期関数**複雑な条件ロジックのための非同期関数
無効化されたツールは実行時に LLM から完全に隠されるため、次の用途に有効です。
無効なツールはランタイムで LLM から完全に非表示になるため、次の用途に役立ちます。
- ユーザー権限に基づく機能ゲート
- 環境ツール可用性 ( dev vs prod )
- 異なるツール構成の A/B テスト
- ランタイム状態に基づく動的ツールフィルタリング
- ユーザー権限に基づく機能制御
- 環境固有のツール可用性(開発環境と本番環境)
- 異なるツール設定の A/B テスト
- ランタイム状態に基づく動的ツールフィルタリング
## Experimental: Codex tool
## 実験的機能:Codex ツール
`codex_tool` は Codex CLI をラップし、エージェントがツール呼び出し中にワークスペーススコープのタスク ( shell、ファイル編集、 MCP ツール ) を実行できるようにします。このは実験的であり、変更される可能性があります。
`codex_tool` は Codex CLI をラップし、エージェントがツール呼び出し中にワークスペーススコープされたタスク(シェル、ファイル編集、MCP ツールを実行できるようにします。この機能は実験的であり、変更される可能性があります。
現在の run を離れずに、メインエージェントから Codex に境界付きワークスペースタスクを委譲したい場合に使用します。デフォルトのツール名は `codex` です。カスタム名を設定する場合、そは `codex` であるか `codex_` で始まる必要があります。エージェントに複数の Codex ツールがある場合、それぞれ一意名である必要があります。
メインエージェントが現在の実行を離れることなく、範囲が限定されたワークスペースタスクを Codex に委任する場合に使用します。デフォルトのツール名は `codex` です。カスタム名を設定する場合、その名前は `codex` であるか`codex_` で始まる必要があります。エージェントに複数の Codex ツールを含める場合、それぞれ一意の名前を使用する必要があります。
```python
from agents import Agent
@@ -788,7 +787,7 @@ agent = Agent(
sandbox_mode="workspace-write",
working_directory="/path/to/repo",
default_thread_options=ThreadOptions(
model="gpt-5.4",
model="gpt-5.5",
model_reasoning_effort="low",
network_access_enabled=True,
web_search_mode="disabled",
@@ -803,33 +802,33 @@ agent = Agent(
)
```
まず次のオプショングループから始めてください。
まず次のオプショングループから設定してください。
- 実行面: `sandbox_mode` と `working_directory` は Codex が操作できる場所を定義します。これらは組み合わせて設定し、作業ディレクトリが Git リポジトリ内にない場合は `skip_git_repo_check=True` を設定してください。
- スレッドデフォルト: `default_thread_options=ThreadOptions(...)` は、モデル、推論努力、承認ポリシー、追加ディレクトリ、ネットワークアクセス、 Web 検索モードを設定します。レガシーの `web_search_enabled` より `web_search_mode` を優先してください。
- ターンデフォルト: `default_turn_options=TurnOptions(...)` は、`idle_timeout_seconds` や任意のキャンセル `signal` など、ターンごとの動作を設定します。
- ツール I/O: ツール呼び出しには、`{ "type": "text", "text": ... }` または `{ "type": "local_image", "path": ... }` を持つ `inputs` アイテムを少なくとも 1 つ含める必要があります。`output_schema` により構造化 Codex 応答を必須にできます。
- 実行対象:`sandbox_mode` と `working_directory` はCodex が操作できる場所を定義します。これらは組み合わせて使用し、作業ディレクトリが Git リポジトリ内にない場合は `skip_git_repo_check=True` を設定してください。
- スレッドデフォルト`default_thread_options=ThreadOptions(...)` は、モデル、推論強度、承認ポリシー、追加ディレクトリ、ネットワークアクセス、Web 検索モードを設定します。従来の `web_search_enabled` より `web_search_mode` を優先してください。
- ターンデフォルト`default_turn_options=TurnOptions(...)` は、`idle_timeout_seconds` やオプションのキャンセル `signal` など、ターンごとの動作を設定します。
- ツール I/Oツール呼び出しには、`{ "type": "text", "text": ... }` または `{ "type": "local_image", "path": ... }` を持つ `inputs` 項目を少なくとも 1 つ含める必要があります。`output_schema` を使用すると、構造化された Codex レスポンスを必須にできます。
スレッド再利用と永続化は別々制御す。
スレッド再利用と永続化は別々制御されます。
- `persist_session=True` は、同ツールインスタンスへの繰り返し呼び出しで 1 つの Codex スレッドを再利用します。
- `use_run_context_thread_id=True` は、同じ変コンテキストオブジェクトを共有する run 間で、 run コンテキスト内にスレッド ID を保存して再利用します。
- スレッド ID の優先順位は、呼び出しごとの `thread_id`、次に ( 有効時 ) run-context スレッド ID、次に設定済み `thread_id` オプションです。
- デフォルト run-context キーは、`name="codex"` は `codex_thread_id`、`name="codex_<suffix>"` は `codex_thread_id_<suffix>` です。`run_context_thread_id_key` で上書きできます。
- `persist_session=True` は、同ツールインスタンスへの繰り返し呼び出しで 1 つの Codex スレッドを再利用します。
- `use_run_context_thread_id=True` は、同じ変更可能なコンテキストオブジェクトを共有する複数の実行にわたり、実行コンテキスト内にスレッド ID を保存して再利用します。
- スレッド ID の優先順位は、呼び出しごとの `thread_id`、実行コンテキストのスレッド ID(有効な場合)、設定済み `thread_id` オプションの順です。
- デフォルトの実行コンテキストキーは、`name="codex"` の場合は `codex_thread_id`、`name="codex_<suffix>"` の場合は `codex_thread_id_<suffix>` です。`run_context_thread_id_key` でオーバーライドできます。
ランタイム設定:
ランタイム設定
- 認証: `CODEX_API_KEY` (推奨) または `OPENAI_API_KEY` を設定するか、`codex_options={"api_key": "..."}` を渡します。
- ランタイム: `codex_options.base_url` は CLI の base URL を上書きします。
- バイナリ解決: CLI パスを固定するには `codex_options.codex_path_override` (または `CODEX_PATH`) を設定します。設定しない場合、 SDK は `PATH` から `codex` を解決し、その後バンドル済み vendor バイナリへフォールバックします。
- 環境: `codex_options.env` はサブプロセス環境を完全に制御します。これを指定すると、サブプロセスは `os.environ` を継承しません。
- ストリーム制限: `codex_options.codex_subprocess_stream_limit_bytes` (または `OPENAI_AGENTS_CODEX_SUBPROCESS_STREAM_LIMIT_BYTES`) は stdout / stderr リーダー制限を制御します。有効範囲は `65536` から `67108864`、デフォルトは `8388608` です。
- ストリーミング: `on_stream` はスレッド / ターンのライフサイクルイベントとアイテムイベント (`reasoning`、`command_execution`、`mcp_tool_call`、`file_change`、`web_search`、`todo_list`、`error` のアイテム更新) を受け取ります。
- 出力: 結果には `response`、`usage`、`thread_id` が含まれます。usage は `RunContextWrapper.usage` に追加されます。
- 認証`CODEX_API_KEY`(推奨)または `OPENAI_API_KEY` を設定するか、`codex_options={"api_key": "..."}` を渡します。
- ランタイム`codex_options.base_url` は CLI のベース URL をオーバーライドします。
- バイナリ解決CLI パスを固定するには`codex_options.codex_path_override`または `CODEX_PATH`を設定します。それ以外の場合、SDK は `PATH` から `codex` を解決し、見つからなければ同梱のベンダーバイナリを使用します。
- 環境`codex_options.env` はサブプロセス環境を完全に制御します。指定した場合、サブプロセスは `os.environ` を継承しません。
- ストリーム制限`codex_options.codex_subprocess_stream_limit_bytes`または `OPENAI_AGENTS_CODEX_SUBPROCESS_STREAM_LIMIT_BYTES`)は、stdoutstderr リーダー制限を制御します。有効範囲は `65536` から `67108864`、デフォルトは `8388608` です。
- ストリーミング`on_stream` はスレッドターンのライフサイクルイベントと項目イベント`reasoning`、`command_execution`、`mcp_tool_call`、`file_change`、`web_search`、`todo_list`、`error` の項目更新)を受け取ります。
- 出力:実行結果には `response`、`usage`、`thread_id` が含まれます。使用量は `RunContextWrapper.usage` に追加されます。
参照:
リファレンス:
- [Codex tool API reference](ref/extensions/experimental/codex/codex_tool.md)
- [ThreadOptions reference](ref/extensions/experimental/codex/thread_options.md)
- [TurnOptions reference](ref/extensions/experimental/codex/turn_options.md)
- 完全に実行可能なサンプル`examples/tools/codex.py` と `examples/tools/codex_same_thread.py` を参照してください。
- [Codex ツール API リファレンス](ref/extensions/experimental/codex/codex_tool.md)
- [ThreadOptions リファレンス](ref/extensions/experimental/codex/thread_options.md)
- [TurnOptions リファレンス](ref/extensions/experimental/codex/turn_options.md)
- 実行可能な完全なサンプルについては、`examples/tools/codex.py` と `examples/tools/codex_same_thread.py` を参照してください。
+98 -50
View File
@@ -4,53 +4,96 @@ search:
---
# トレーシング
Agents SDK には組み込みのトレーシングが含まれており、エージェント実行中のイベント( LLM 生成、ツール呼び出し、ハンドオフ、ガードレール、さらには発生したカスタムイベント)を包括的に記録します。[Traces ダッシュボード](https://platform.openai.com/traces) を使用すると、開発中および本番環境でワークフローをデバッグ、可視化、監視できます。
Agents SDK には組み込みのトレーシングが含まれており、エージェント実行中のイベント(LLM 生成、ツール呼び出し、ハンドオフ、ガードレール、さらには発生したカスタムイベントまで)を包括的に収集します。[Traces ダッシュボード](https://platform.openai.com/traces)を使用すると、開発中および本番環境でワークフローをデバッグ、可視化、監視できます。
!!!note
トレーシングはデフォルトで有効です。一般的な方法として、次の 3 つで無効化できます
トレーシングはデフォルトで有効です。一般的には次の 3 つの方法で無効化できます:
1. 環境変数 `OPENAI_AGENTS_DISABLE_TRACING=1` を設定して、グローバルにトレーシングを無効化できます
2. [`set_tracing_disabled(True)`][agents.set_tracing_disabled] を使って、コード内でグローバルにトレーシングを無効化できます
3. [`agents.run.RunConfig.tracing_disabled`][] を `True` に設定して、単一の実行トレーシングを無効化できます
1. 環境変数 `OPENAI_AGENTS_DISABLE_TRACING=1` を設定することで、トレーシングをグローバルに無効化できます
2. コード内で [`set_tracing_disabled(True)`][agents.set_tracing_disabled] を使用して、トレーシングをグローバルに無効化できます
3. [`agents.run.RunConfig.tracing_disabled`][] を `True` に設定することで、単一の実行に対してトレーシングを無効化できます
***OpenAI の API を使用し、Zero Data Retention ( ZDR ) ポリシーの下で運用している組織では、トレーシングは利用できません。***
***OpenAI の API を使用し、Zero Data Retention (ZDR) ポリシーの下で運用している組織では、トレーシングは利用できません。***
## トレースとスパン
- **トレース** は「ワークフロー」の単一のエンドツーエンド操作を表します。スパンで構成されます。トレースには次のプロパティがあります
- `workflow_name`: 論理的なワークフローまたはアプリです。たとえば「Code generation」や「Customer service」です。
- **トレース**「ワークフロー」の単一のエンドツーエンド操作を表します。トレースはスパンで構成されます。トレースには次のプロパティがあります:
- `workflow_name`: 論理的なワークフローまたはアプリです。たとえば「コード生成」や「カスタマーサービス」です。
- `trace_id`: トレースの一意な ID です。指定しない場合は自動生成されます。形式は `trace_<32_alphanumeric>` である必要があります。
- `group_id`: 同じ会話からの複数のトレースを関連付けるための任意のグループ ID です。たとえば、チャットスレッド ID を使用できます。
- `group_id`: 任意のグループ ID で、同じ会話からの複数のトレースを関連付けるために使用します。たとえば、チャットスレッド ID を使用できます。
- `disabled`: True の場合、トレースは記録されません。
- `metadata`: トレースの任意のメタデータです。
- **スパン** は開始時刻と終了時刻を持つ操作を表します。スパンには次があります
- **スパン**開始時刻と終了時刻を持つ操作を表します。スパンには次のものがあります:
- `started_at``ended_at` のタイムスタンプ。
- `trace_id`: 属するトレースを表します
- `trace_id`: 属するトレースを表します
- `parent_id`: このスパンの親スパン(存在する場合)を指します
- `span_data`: スパンに関する情報です。たとえば `AgentSpanData` にはエージェントの情報`GenerationSpanData` には LLM 生成の情報などが含まれます。
- `span_data`: スパンに関する情報です。たとえば`AgentSpanData` にはエージェントに関する情報が含まれ`GenerationSpanData` には LLM 生成に関する情報が含まれます。
## デフォルトトレーシング
## デフォルトトレーシング
デフォルトで、 SDK は次をトレースします
デフォルトで、SDK は次をトレースします:
- `Runner.{run, run_sync, run_streamed}()` 全体は `trace()` でラップされます。
- エージェントが実行されるたびに、`agent_span()` でラップされます
- LLM 生成は `generation_span()` でラップされます
- 関数ツール呼び出しはそれぞれ `function_span()` でラップされます
- 関数ツール呼び出しは `function_span()` でラップされます
- ガードレールは `guardrail_span()` でラップされます
- ハンドオフは `handoff_span()` でラップされます
- 音声入力( speech-to-text )は `transcription_span()` でラップされます
- 音声出力( text-to-speech )は `speech_span()` でラップされます
- 関連する音声スパンは `speech_group_span()`子になる場合があります
- 音声入力(音声からテキストへの変換)は `transcription_span()` でラップされます
- 音声出力(テキストから音声への変換)は `speech_span()` でラップされます
- 関連する音声スパンは`speech_group_span()`下に親子関係として配置される場合があります
デフォルトで、トレース名は「Agent workflow」です。`trace` を使用する場合はこの名前を設定できます。また、[`RunConfig`][agents.run.RunConfig] で名前や他のプロパティを設定することもできます。
デフォルトで、トレース名は「Agent workflow」です。`trace` を使用する場合はこの名前を設定できます。また、[`RunConfig`][agents.run.RunConfig] で名前やその他のプロパティを構成できます。
さらに、[カスタムトレープロセッサー](#custom-tracing-processors) を設定して、トレースを他の送信先へプッシュできます(置き換えまたは二次送信先として)。
さらに、[カスタムトレーシングプロセッサー](#custom-tracing-processors)を設定して、トレースを他の送信先へ送ることもできます(置き換えまたは副次的な送信先として)。
## 上位レベルトレース
## 長時間稼働するワーカーと即時エクスポート
場合によっては、`run()` への複数回の呼び出しを 1 つのトレースに含めたいことがあります。これを行うには、コード全体を `trace()` でラップします。
デフォルトの [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] は、数秒ごとにバックグラウンドでトレースをエクスポートします。メモリ内キューがサイズトリガーに達した場合はそれより早くエクスポートし、プロセス終了時には最終フラッシュも行います。Celery、RQ、Dramatiq、FastAPI のバックグラウンドタスクなどの長時間稼働するワーカーでは、通常、追加のコードなしでトレースが自動的にエクスポートされますが、各ジョブ完了直後に Traces ダッシュボードに表示されない場合があります。
作業単位の終了時に即時配信を保証する必要がある場合は、トレースコンテキストが終了した後に [`flush_traces()`][agents.tracing.flush_traces] を呼び出してください。
```python
from agents import Runner, flush_traces, trace
@celery_app.task
def run_agent_task(prompt: str):
try:
with trace("celery_task"):
result = Runner.run_sync(agent, prompt)
return result.final_output
finally:
flush_traces()
```
```python
from fastapi import BackgroundTasks, FastAPI
from agents import Runner, flush_traces, trace
app = FastAPI()
def process_in_background(prompt: str) -> None:
try:
with trace("background_job"):
Runner.run_sync(agent, prompt)
finally:
flush_traces()
@app.post("/run")
async def run(prompt: str, background_tasks: BackgroundTasks):
background_tasks.add_task(process_in_background, prompt)
return {"status": "queued"}
```
[`flush_traces()`][agents.tracing.flush_traces] は、現在バッファーされているトレースとスパンがエクスポートされるまでブロックします。そのため、部分的に構築されたトレースをフラッシュしないよう、`trace()` が閉じた後に呼び出してください。デフォルトのエクスポート遅延で問題ない場合は、この呼び出しを省略できます。
## 上位レベルのトレース
場合によっては、`run()` への複数回の呼び出しを単一のトレースの一部にしたいことがあります。コード全体を `trace()` でラップすることで実現できます。
```python
from agents import Agent, Runner, trace
@@ -65,60 +108,60 @@ async def main():
print(f"Rating: {second_result.final_output}")
```
1. `Runner.run` への 2 回の呼び出しが `with trace()` でラップされているため、個々の実行は 2 つのトレースを作成するのではなく、全体のトレースの一部になります。
1. 2 回の `Runner.run` 呼び出しが `with trace()` でラップされているため、個々の実行は 2 つのトレースを作成するのではなく、全体のトレースの一部になります。
## トレースの作成
[`trace()`][agents.tracing.trace] 関数を使用してトレースを作成できます。トレースは開始と終了が必要です。方法は 2 つあります
[`trace()`][agents.tracing.trace] 関数を使用してトレースを作成できます。トレースは開始し、終了する必要があります。その方法は 2 つの選択肢があります:
1. **推奨**: コンテキストマネージャーとしてトレースを使用します。つまり `with trace(...) as my_trace` す。これにより、適切なタイミングでトレースが自動的に開始終了されます。
1. **推奨**: トレースをコンテキストマネージャーとして使用します。つまり`with trace(...) as my_trace` のように使用します。これにより、適切なタイミングでトレースが自動的に開始および終了されます。
2. [`trace.start()`][agents.tracing.Trace.start] と [`trace.finish()`][agents.tracing.Trace.finish] を手動で呼び出すこともできます。
現在のトレースは Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) を介して追跡されます。これは並行処理でも自動的に機能することを意味します。トレースを手動で開始 / 終了する場合は、現在のトレースを更新するために `start()` / `finish()``mark_as_current``reset_current` を渡す必要があります。
現在のトレースはPython の [`contextvar`](https://docs.python.org/3/library/contextvars.html) を介して追跡されます。これは並行処理でも自動的に機能することを意味します。手動でトレースを開始/終了する場合は、現在のトレースを更新するために`start()`/`finish()``mark_as_current``reset_current` を渡す必要があります。
## スパンの作成
さまざまな [`*_span()`][agents.tracing.create] メソッドを使てスパンを作成できます。一般に、スパンを手動で作成する必要はありません。カスタムスパン情報を追跡するために [`custom_span()`][agents.tracing.custom_span] 関数利用できます。
各種 [`*_span()`][agents.tracing.create] メソッドを使用してスパンを作成できます。通常、手動でスパンを作成する必要はありません。カスタムスパン情報を追跡するために[`custom_span()`][agents.tracing.custom_span] 関数利用できます。
スパンは自動的に現在のトレースの一部となり、最も近い現在のスパンの下にネストされます。これは Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) 追跡されます。
スパンは自動的に現在のトレースの一部となり、最も近い現在のスパンの下にネストされます。この現在のスパンは、Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) を介して追跡されます。
## 機密データ
一部のスパンは、機密性のある可能性があるデータを取得する場合があります。
一部のスパンは、潜在的に機密性の高いデータを取得する場合があります。
`generation_span()` は LLM 生成の入力 / 出力を保存し、`function_span()` は関数呼び出しの入力 / 出力を保存します。これらには機密データが含まれる可能性があるため、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] そのデータの取得を無効化できます。
`generation_span()` は LLM 生成の入出力を保存し、`function_span()` は関数呼び出しの入出力を保存します。これらには機密データが含まれる可能性があるため、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] を使用してそのデータの取得を無効化できます。
同様に、音声スパンにはデフォルトで入力 / 出力音声の base64 エンコードされた PCM データが含まれます。[`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] を設定することで、この音声データの取得を無効化できます。
同様に、音声スパンにはデフォルトで入力音声と出力音声の base64 エンコードされた PCM データが含まれます。この音声データの取得は、[`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] を構成することで無効化できます。
デフォルトで `trace_include_sensitive_data``True` です。コードを変更せずにデフォルトを設定するには、アプリ実行前に環境変数 `OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA``true/1` または `false/0` として export します。
デフォルトでは、`trace_include_sensitive_data``True` です。アプリ実行する前に `OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA` 環境変数`true/1` または `false/0` にエクスポートすることで、コードを書かずにデフォルトを設定できます。
## カスタムトレーシングプロセッサー
トレーシングの高レベルアーキテクチャは次のとおりです
トレーシングの高レベルアーキテクチャは次のとおりです:
- 初期化時に、トレース作成を担当するグローバルな [`TraceProvider`][agents.tracing.setup.TraceProvider] を作成します。
- `TraceProvider` に [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] を設定し、トレース / スパンをバッチで [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] に送信します。これはスパンとトレースをバッチで OpenAI バックエンドへエクスポートします。
- 初期化時に、グローバルな [`TraceProvider`][agents.tracing.setup.TraceProvider] を作成します。これはトレースの作成を担います。
- `TraceProvider` は、トレース/スパンをバッチ単位で [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] に送信する [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] で構成します。`BackendSpanExporter` は、スパンとトレースをバッチ単位で OpenAI バックエンドへエクスポートします。
このデフォルト設定をカスタマイズし、代替または追加バックエンドへトレースを送信したり、エクスポーターの動作を変更したりするには、次の 2 つの方法があります
このデフォルト設定をカスタマイズし、代替または追加バックエンドへトレースを送信したり、エクスポーターの動作を変更したりするには、2 つの選択肢があります:
1. [`add_trace_processor()`][agents.tracing.add_trace_processor] は、準備完了時にトレーススパンを受け取る**追加**のトレースプロセッサーを追加できます。これにより、OpenAI バックエンドへの送信に加えて独自処理を実行できます。
2. [`set_trace_processors()`][agents.tracing.set_trace_processors] 、デフォルトプロセッサーを独自のトレースプロセッサーで**置き換え**できます。これは、そうする `TracingProcessor` を含めない限り、トレース OpenAI バックエンド送信されないことを意味します
1. [`add_trace_processor()`][agents.tracing.add_trace_processor] を使用すると、トレーススパンが準備でき次第それらを受け取る **追加の** トレースプロセッサーを追加できます。これにより、OpenAI バックエンドへトレースを送信することに加えて独自処理を行えます。
2. [`set_trace_processors()`][agents.tracing.set_trace_processors] を使用すると、デフォルトプロセッサーを独自のトレースプロセッサーで **置き換え** ことができます。つまり、その処理を行う `TracingProcessor` を含めない限り、トレース OpenAI バックエンド送信されません
## OpenAI モデルでのトレーシング
## OpenAI 以外のモデルでのトレーシング
OpenAI API キーを非 OpenAI モデルと共に使用して、トレーシングを無効化することなく OpenAI Traces ダッシュボードで無料トレーシングを有効できます。
OpenAI 以外のモデルで OpenAI API キーを使用すると、トレーシングを無効化する必要なくOpenAI Traces ダッシュボードで無料トレーシングを有効できます。アダプターの選択とセットアップ上の注意事項については、Models ガイドの[サードパーティアダプター](models/index.md#third-party-adapters)セクションを参照してください。
```python
import os
from agents import set_tracing_export_api_key, Agent, Runner
from agents.extensions.models.litellm_model import LitellmModel
from agents.extensions.models.any_llm_model import AnyLLMModel
tracing_api_key = os.environ["OPENAI_API_KEY"]
set_tracing_export_api_key(tracing_api_key)
model = LitellmModel(
model="your-model-name",
model = AnyLLMModel(
model="your-provider/your-model-name",
api_key="your-api-key",
)
@@ -128,7 +171,7 @@ agent = Agent(
)
```
単一の実行のみ別のトレーシングキーが必要な場合は、グローバルエクスポーターを変更する代わりに `RunConfig` 経由で渡してください。
単一の実行に対してのみ別のトレーシングキーが必要な場合は、グローバルエクスポーターを変更する代わりに `RunConfig` 経由で渡してください。
```python
from agents import Runner, RunConfig
@@ -141,20 +184,20 @@ await Runner.run(
```
## 追加の注意事項
- Openai Traces ダッシュボードで無料トレースを確認します。
- OpenAI Traces ダッシュボードで無料トレースを表示できます。
## エコシステム連携
## エコシステム統合
次のコミュニティおよびベンダー連携は、OpenAI Agents SDK のトレーシングーフェスをサポートしています。
次のコミュニティおよびベンダー統合は、OpenAI Agents SDK のトレーシングインターフェスをサポートしています。
### 外部トレーシングプロセッサー一覧
- [Weights & Biases](https://weave-docs.wandb.ai/guides/integrations/openai_agents)
- [Arize-Phoenix](https://docs.arize.com/phoenix/tracing/integrations-tracing/openai-agents-sdk)
- [Future AGI](https://docs.futureagi.com/future-agi/products/observability/auto-instrumentation/openai_agents)
- [MLflow (self-hosted/OSS)](https://mlflow.org/docs/latest/tracing/integrations/openai-agent)
- [MLflow (Databricks hosted)](https://docs.databricks.com/aws/en/mlflow/mlflow-tracing#-automatic-tracing)
- [MLflow (セルフホスト/OSS)](https://mlflow.org/docs/latest/tracing/integrations/openai-agent)
- [MLflow (Databricks ホスト)](https://docs.databricks.com/aws/en/mlflow/mlflow-tracing#-automatic-tracing)
- [Braintrust](https://braintrust.dev/docs/guides/traces/integrations#openai-agents-sdk)
- [Pydantic Logfire](https://logfire.pydantic.dev/docs/integrations/llms/openai/#openai-agents)
- [AgentOps](https://docs.agentops.ai/v1/integrations/agentssdk)
@@ -172,4 +215,9 @@ await Runner.run(
- [Agenta](https://docs.agenta.ai/observability/integrations/openai-agents)
- [PostHog](https://posthog.com/docs/llm-analytics/installation/openai-agents)
- [Traccia](https://traccia.ai/docs/integrations/openai-agents)
- [PromptLayer](https://docs.promptlayer.com/languages/integrations#openai-agents-sdk)
- [PromptLayer](https://docs.promptlayer.com/languages/integrations#openai-agents-sdk)
- [HoneyHive](https://docs.honeyhive.ai/v2/integrations/openai-agents)
- [Asqav](https://www.asqav.com/docs/integrations#openai-agents)
- [Datadog](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation/?tab=python#openai-agents)
- [Latitude](https://docs.latitude.so/telemetry/frameworks/openai-agents)
- [DProvenanceKit](https://dprovenance.dev/openai-agents/)
+19 -28
View File
@@ -2,24 +2,24 @@
search:
exclude: true
---
# 使用方法
# 使用
Agents SDK は、実行ごとのトークン使用量を自動的に追跡します。実行コンテキストからアクセスでき、コスト監視、制限の適用、分析記録に利用できます。
Agents SDK は、すべての実行についてトークン使用量を自動的に追跡します。使用量には実行コンテキストからアクセスでき、コスト監視、制限の適用、分析記録に利用できます。
## 追跡対象
- **requests**: 実行された LLM API 呼び出し
- **input_tokens**: 送信された入力トークン総数
- **output_tokens**: 受信た出力トークン総数
- **requests**: 実行された LLM API 呼び出し
- **input_tokens**: 送信された入力トークンの合計
- **output_tokens**: 受信された出力トークンの合計
- **total_tokens**: 入力 + 出力
- **request_usage_entries**: リクエストごとの使用量内訳の一覧
- **request_usage_entries**: リクエストごとの使用量内訳のリスト
- **details**:
- `input_tokens_details.cached_tokens`
- `output_tokens_details.reasoning_tokens`
## 実行からの使用量へのアクセス
`Runner.run(...)` の後、`result.context_wrapper.usage`使用量にアクセスします。
`Runner.run(...)` の後、使用量には `result.context_wrapper.usage` 経由でアクセスします。
```python
result = await Runner.run(agent, "What's the weather in Tokyo?")
@@ -31,29 +31,20 @@ print("Output tokens:", usage.output_tokens)
print("Total tokens:", usage.total_tokens)
```
使用量は、実行中のすべてのモデル呼び出し(ツール呼び出しハンドオフを含む)集計されます。
使用量は、この実行中のすべてのモデル呼び出し(ツール呼び出しハンドオフを含む)にわたって集計されます。
### LiteLLM モデルでの使用量の有効化
### サードパーティ製アダプターでの使用量の有効化
LiteLLM プロバイダーは、デフォルトでは使用量メトリクスを報告しません。[`LitellmModel`][agents.extensions.models.litellm_model.LitellmModel] を使用している場合は、LiteLLM のレスポンスが `result.context_wrapper.usage` を埋めるよう、エージェントに `ModelSettings(include_usage=True)` を渡してください。設定手順とコード例については、Models ガイドの [LiteLLM note](models/index.md#litellm) を参照してください。
使用量のレポートは、サードパーティ製アダプターやプロバイダーバックエンドによって異なります。アダプター経由のモデルに依存しており、正確な `result.context_wrapper.usage` の値が必要な場合は:
```python
from agents import Agent, ModelSettings, Runner
from agents.extensions.models.litellm_model import LitellmModel
- `AnyLLMModel` では、上流プロバイダーが使用量を返す場合、使用量は自動的に伝播されます。ストリーミングされた Chat Completions バックエンドでは、使用量チャンクが出力される前に `ModelSettings(include_usage=True)` が必要になる場合があります。
- `LitellmModel` では、一部のプロバイダーバックエンドはデフォルトで使用量を報告しないため、`ModelSettings(include_usage=True)` が必要になることがよくあります。
agent = Agent(
name="Assistant",
model=LitellmModel(model="your/model", api_key="..."),
model_settings=ModelSettings(include_usage=True),
)
result = await Runner.run(agent, "What's the weather in Tokyo?")
print(result.context_wrapper.usage.total_tokens)
```
Models ガイドの [サードパーティ製アダプター](models/index.md#third-party-adapters) セクションにあるアダプター固有の注記を確認し、デプロイ予定の正確なプロバイダーバックエンドを検証してください。
## リクエストごとの使用量追跡
SDK は、`request_usage_entries` 内の API リクエストごとの使用量を自動追跡します。これは詳細なコスト計算やコンテキストウィンドウ消費量の監視に有用です。
SDK は、各 API リクエストの使用量を `request_usage_entries` で自動的に追跡します。これは詳細なコスト計算やコンテキストウィンドウ消費量の監視に役立ちます。
```python
result = await Runner.run(agent, "What's the weather in Tokyo?")
@@ -64,7 +55,7 @@ for i, request in enumerate(result.context_wrapper.usage.request_usage_entries):
## セッションでの使用量へのアクセス
`Session`(例: `SQLiteSession`)を使用する場合、`Runner.run(...)` の各呼び出しはその特定の実行に対する使用量を返します。セッションは文脈のために会話履歴を持しますが、各実行の使用量は独立しています。
`Session`(例: `SQLiteSession`)を使用する場合、`Runner.run(...)` の各呼び出しはその特定の実行使用量を返します。セッションはコンテキスト用に会話履歴を持しますが、各実行の使用量は独立しています。
```python
session = SQLiteSession("my_conversation")
@@ -76,11 +67,11 @@ second = await Runner.run(agent, "Can you elaborate?", session=session)
print(second.context_wrapper.usage.total_tokens) # Usage for second run
```
セッションは実行間会話コンテキストを保持しますが、各 `Runner.run()` 呼び出し返される使用量メトリクスは、その特定の実行のみを表します。セッションでは、前のメッセージが各実行入力として再投入される場合があり、その結果、後続ターンの入力トークン数に影響します。
セッションは実行間会話コンテキストを保持しますが、各 `Runner.run()` 呼び出しから返される使用量メトリクスは、その特定の実行のみを表します。セッションでは、前のメッセージが各実行入力として再投入される場合があり、これにより以降のターンにおける入力トークン数に影響します。
## フックでの使用量の利用
`RunHooks` を使用している場合、各フックに渡される `context` オブジェクトには `usage` が含まれます。これにより、ライフサイクルの重要なタイミングで使用量を記録できます。
`RunHooks` を使用している場合、各フックに渡される `context` オブジェクトには `usage` が含まれます。これにより、主要なライフサイクルのタイミングで使用量をログ記録できます。
```python
class MyHooks(RunHooks):
@@ -91,9 +82,9 @@ class MyHooks(RunHooks):
## API リファレンス
詳細な API ドキュメントは次を参照してください
詳細な API ドキュメントについては、以下を参照してください:
- [`Usage`][agents.usage.Usage] - 使用量追跡データ構造
- [`RequestUsage`][agents.usage.RequestUsage] - リクエストごとの使用量詳細
- [`RunContextWrapper`][agents.run.RunContextWrapper] - 実行コンテキストから使用量アクセス
- [`RunContextWrapper`][agents.run.RunContextWrapper] - 実行コンテキストから使用量へのアクセス
- [`RunHooks`][agents.run.RunHooks] - 使用量追跡ライフサイクルへのフック
+25 -24
View File
@@ -2,25 +2,25 @@
search:
exclude: true
---
# エージェント可視化
# エージェント可視化
エージェント可視化では、 **Graphviz** を使用してエージェントとその関係を構造化されたグラフィカル表現として生成できます。これは、アプリケーション内でエージェント、ツール、ハンドオフがどのように相互作用するかを理解するのに役立ちます。
エージェント可視化では、 **Graphviz** を使用してエージェントとその関係を構造化されたグラフィカル表現として生成できます。これは、アプリケーション内でエージェント、ツール、ハンドオフがどのように相互作用するかを理解するのに役立ちます。
## インストール
オプションの `viz` 依存関係グループをインストールします
オプションの `viz` 依存関係グループをインストールします:
```bash
pip install "openai-agents[viz]"
```
## グラフ生成
## グラフ生成
`draw_graph` 関数を使用してエージェント可視化を生成できます。この関数は、以下の構成を持つ有向グラフを作成します。
`draw_graph` 関数を使用してエージェント可視化を生成できます。この関数は、次のように表現される有向グラフを作成します。
- **エージェント** は黄色のボックスとして表されます。
- **MCP サーバー** は灰色のボックスとして表されます。
- **ツール** は緑色の楕円として表されます。
- **エージェント** は黄色のボックスとして表されます。
- **MCP サーバー** は灰色のボックスとして表されます。
- **ツール** は緑色の楕円として表されます。
- **ハンドオフ** は、あるエージェントから別のエージェントへの有向エッジです。
### 使用例
@@ -67,37 +67,38 @@ triage_agent = Agent(
draw_graph(triage_agent)
```
![Agent Graph](../assets/images/graph.png)
![エージェントグラフ](../assets/images/graph.png)
これにより、 **トリアージエージェント** の構造と、サブエージェントおよびツールへの接続を視覚的に表すグラフが生成されます。
これにより、 **triage agent** の構造と、サブエージェントおよびツールへの接続を視覚的に表すグラフが生成されます。
## 可視化の理解
生成されグラフには以下が含まれます。
生成されグラフには次のものが含まれます。
- エントリーポイントを示す **開始ノード** (`__start__`)
- 黄色で塗りつぶされた **長方形** として表されるエージェント。
- 緑色で塗りつぶされた **楕円** として表されるツール。
- 灰色で塗りつぶされた **長方形** として表される MCP サーバー。
- エントリーポイントを示す **開始ノード** `__start__`
- 黄色で塗りつぶされた **長方形** として表されるエージェント。
- 緑色で塗りつぶされた **楕円** として表されるツール。
- 灰色で塗りつぶされた **長方形** として表される MCP サーバー。
- 相互作用を示す有向エッジ:
- エージェント間ハンドオフには **実線矢印**
- ツール呼び出しには **点線矢印**
- MCP サーバー呼び出しには **破線矢印**
- 実行が終了する位置を示す **終了ノード** (`__end__`)
- エージェント間ハンドオフを示す **実線矢印**
- ツール呼び出しを示す **点線矢印**
- MCP サーバー呼び出しを示す **破線矢印**
- 実行が終了する場所を示す **終了ノード** `__end__`
**注:** MCP サーバーは `agents` パッケージの最近のバージョン ( **v0.2.8** で確認済み ) で描画されます。可視化 MCP ボックスが表示されない場合は、最新リリースにアップグレードしてください。
**注:** MCP サーバーは、最近のバージョンの `agents` パッケージで描画されます( **v0.2.8** で確認済み。可視化 MCP ボックスが表示されない場合は、最新リリースにアップグレードしてください。
## グラフのカスタマイズ
### グラフ表示
デフォルトでは、 `draw_graph` はグラフをインライン表示します。グラフを別ウィンドウで表示するには、次のように記述します
### グラフ表示
デフォルトでは、 `draw_graph` はグラフをインライン表示します。グラフを別ウィンドウで表示するには、次のように記述します:
```python
draw_graph(triage_agent).view()
```
### グラフ保存
デフォルトでは、 `draw_graph` はグラフをインライン表示します。ファイルとして保存するには、ファイル名を指定します
### グラフ保存
デフォルトでは、 `draw_graph` はグラフをインライン表示します。ファイルとして保存するには、ファイル名を指定します:
```python
draw_graph(triage_agent, filename="agent_graph")
+20 -18
View File
@@ -4,7 +4,7 @@ search:
---
# パイプラインとワークフロー
[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] は、エージェントワークフローを音声アプリに簡単に変換できるクラスです。実行するワークフローを渡すと、パイプラインが入力音声の文字起こし、音声終了検出、適切なタイミングでのワークフロー呼び出し、そしてワークフロー出力の音声への変換を担います。
[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] は、エージェントワークフローを音声アプリに変換しやすくするクラスです。実行するワークフローを渡すと、パイプラインが入力音声の文字起こし、音声終了検出、適切なタイミングでのワークフロー呼び出し、ワークフロー出力の音声への変換を処理します。
```mermaid
graph LR
@@ -34,29 +34,29 @@ graph LR
## パイプラインの設定
パイプラインを作成する、いくつかの項目を設定できます。
パイプラインを作成するときに、いくつかの項目を設定できます。
1. [`workflow`][agents.voice.workflow.VoiceWorkflowBase]新しい音声が文字起こしされるたびに実行されるコードです。
2. 使用る [`speech-to-text`][agents.voice.model.STTModel] および [`text-to-speech`][agents.voice.model.TTSModel] モデル
3. [`config`][agents.voice.pipeline_config.VoicePipelineConfig]次のような項目を設定できます。
- モデルプロバイダー(モデル名をモデルにマッピングできます)
- トレーシングトレーシングを無効するかどうか、音声ファイルをアップロードするかどうか、ワークフロー名、トレース ID など
- TTS および STT モデルの設定プロンプト、言語、使用するデータ型など
1. [`workflow`][agents.voice.workflow.VoiceWorkflowBase]新しい音声が文字起こしされるたびに実行されるコードです。
2. 使用される [`speech-to-text`][agents.voice.model.STTModel] モデルと [`text-to-speech`][agents.voice.model.TTSModel] モデル
3. [`config`][agents.voice.pipeline_config.VoicePipelineConfig]次のような項目を設定できます。
- モデル名をモデルにマッピングできるモデルプロバイダー
- トレーシングトレーシングを無効するか、音声ファイルをアップロードするか、ワークフロー名、トレース ID などを含みます。
- TTS モデルと STT モデルの設定プロンプト、言語、使用するデータ型などです。
## パイプラインの実行
パイプラインは [`run()`][agents.voice.pipeline.VoicePipeline.run] メソッドで実行でき、音声入力を 2 つの形式で渡せます。
[`run()`][agents.voice.pipeline.VoicePipeline.run] メソッドを通じてパイプラインを実行できます。このメソッドでは、音声入力を 2 つの形式で渡せます。
1. [`AudioInput`][agents.voice.input.AudioInput]:音声の全文書き起こしがすでにあり、それに対する結果だけを生成したい場合に使用します。話者が話し終えたタイミングを検出する必要がないケースで有用です。たとえば、事前録音音声がある場合や、ユーザーが話し終えたことが明確な push-to-talk アプリなどです。
2. [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput]ユーザーが話し終えたことを検出する必要がある可能性がある場合に使用します。検出された音声チャンクを順次プッシュでき、音声パイプラインは「activity detection」と呼ばれるプロセスにより、適切なタイミングで自動的にエージェントワークフローを実行します。
1. [`AudioInput`][agents.voice.input.AudioInput] は、完全な音声入力があり、それに対する実行結果だけを生成したい場合に使用します。これは、話者が話し終えたタイミングを検出する必要がない場合に便利です。たとえば、事前録音された音声がある場合や、ユーザーが話し終えたことが明確なプッシュ・トゥ・トークアプリの場合です。
2. [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] は、ユーザーが話し終えたタイミングを検出する必要がある場合に使用します。検出された音声チャンクをプッシュでき、音声パイプラインは「アクティビティ検出」と呼ばれるプロセスを通じて、適切なタイミングでエージェントワークフローを自動的に実行します。
## 結果
## 実行結果
音声パイプライン実行の結果は [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult] です。これは、発生したイベントをストリーミングできるオブジェクトです。[`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent] にはいくつかの種類があり、たとえば次のものがあります。
音声パイプライン実行の実行結果は [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult] です。これは、イベントが発生したときにストリーミングできるオブジェクトです。[`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent] には、次のような種類があります。
1. [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio]音声チャンクを含みます。
2. [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle]ターンの開始や終了などのライフサイクルイベントを通知します。
3. [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError]エラーイベントです。
1. [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio]音声チャンクを含みます。
2. [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle]ターンの開始や終了などのライフサイクルイベントを通知します。
3. [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError]エラーイベントです。
```python
@@ -65,15 +65,17 @@ result = await pipeline.run(input)
async for event in result.stream():
if event.type == "voice_stream_event_audio":
# play audio
pass
elif event.type == "voice_stream_event_lifecycle":
# lifecycle
pass
elif event.type == "voice_stream_event_error":
# error
...
pass
```
## ベストプラクティス
### 割り込み
Agents SDK は現在、[`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] に対する組み込みの割り込みサポートを提供していません。代わりに、検出された各ターンごとに、ワークフローの個の実行トリガーされます。アプリケーション内で割り込みを扱いたい場合は、[`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] イベントをリッスンできます。`turn_started` は、新しいターンが文字起こしされ処理が開始されことを示します。`turn_ended` は、該当ターンのすべての音声がディスパッチされた後にトリガーされます。これらのイベントを使て、モデルがターンを開始したときに話者のマイクをミュートし、ターンに関連する音声をすべてフラッシュした後にミュート解除するといった実装が可能です。
Agents SDK は現在、[`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 向けの組み込みの割り込み処理を提供していません。代わりに、検出された各ターンワークフローの個の実行トリガーます。アプリケーション内で割り込みを処理したい場合は、[`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] イベントをリッスンできます。`turn_started` は、新しいターンが文字起こしされ処理が開始されことを示します。`turn_ended` は、対応するターンのすべての音声が送出された後にトリガーされます。これらのイベントを使用して、モデルがターンを開始したときに話者のマイクをミュートし、そのターンに関連するすべての音声をフラッシュした後にミュート解除できます。
+18 -18
View File
@@ -6,19 +6,19 @@ search:
## 前提条件
Agents SDK の基本的な [クイックスタート手順](../quickstart.md) に従い、仮想環境をセットアップしていることを確認してください。次に、 SDK からオプションの音声依存関係をインストールします。
Agents SDK の基本的な[クイックスタート手順](../quickstart.md)に従い、仮想環境をセットアップしていることを確認してください。次に、SDK オプションの音声依存パッケージをインストールします。
```bash
pip install 'openai-agents[voice]'
```
## 概念
## 基本概念
主に理解しておくべき概念は [`VoicePipeline`][agents.voice.pipeline.VoicePipeline] で、これは 3 ステップのプロセスです。
知っておくべき主要な概念は、3 ステップのプロセスである [`VoicePipeline`][agents.voice.pipeline.VoicePipeline] です。
1. 音声認識モデルを実行し、音声をテキストに変換します。
2. コード(通常はエージェントオーケストレーションのワークフロー)を実行し、結果を生成します。
3. 音声合成モデルを実行し、結果のテキストを音声に戻します。
1. 音声テキスト変換モデルを実行し、音声をテキストに変換します。
2. 通常はエージェント型ワークフローであるコードを実行し、結果を生成します。
3. テキスト音声変換モデルを実行し、結果のテキストを音声に戻します。
```mermaid
graph LR
@@ -48,7 +48,7 @@ graph LR
## エージェント
まず、いくつかの Agents をセットアップしましょう。この SDK でエージェントを構築したことがあれば、ここは馴染みのある内容です。複数の Agents と、ハンドオフ、ツールを用意します。
まず、いくつかのエージェントをセットアップしま。この SDK でエージェントを構築した経験があれば、馴染みのある作業でしょう。ここでは、2 つのエージェント、1 つのハンドオフ、1 つのツールを用意します。
```python
import asyncio
@@ -72,19 +72,19 @@ def get_weather(city: str) -> str:
spanish_agent = Agent(
name="Spanish",
handoff_description="A spanish speaking agent.",
handoff_description="A Spanish-speaking agent.",
instructions=prompt_with_handoff_instructions(
"You're speaking to a human, so be polite and concise. Speak in Spanish.",
),
model="gpt-5.4",
model="gpt-5.6-sol",
)
agent = Agent(
name="Assistant",
instructions=prompt_with_handoff_instructions(
"You're speaking to a human, so be polite and concise. If the user speaks in Spanish, handoff to the spanish agent.",
"You're speaking to a human, so be polite and concise. If the user speaks in Spanish, hand off to the Spanish agent.",
),
model="gpt-5.4",
model="gpt-5.6-sol",
handoffs=[spanish_agent],
tools=[get_weather],
)
@@ -92,14 +92,14 @@ agent = Agent(
## 音声パイプライン
ワークフローとして [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow] を使、シンプルな音声パイプラインをセットアップします。
ワークフローとして [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow] を使用し、シンプルな音声パイプラインをセットアップします。
```python
from agents.voice import SingleAgentVoiceWorkflow, VoicePipeline
pipeline = VoicePipeline(workflow=SingleAgentVoiceWorkflow(agent))
```
## パイプライン実行
## パイプライン実行
```python
import numpy as np
@@ -156,19 +156,19 @@ def get_weather(city: str) -> str:
spanish_agent = Agent(
name="Spanish",
handoff_description="A spanish speaking agent.",
handoff_description="A Spanish-speaking agent.",
instructions=prompt_with_handoff_instructions(
"You're speaking to a human, so be polite and concise. Speak in Spanish.",
),
model="gpt-5.4",
model="gpt-5.6-sol",
)
agent = Agent(
name="Assistant",
instructions=prompt_with_handoff_instructions(
"You're speaking to a human, so be polite and concise. If the user speaks in Spanish, handoff to the spanish agent.",
"You're speaking to a human, so be polite and concise. If the user speaks in Spanish, hand off to the Spanish agent.",
),
model="gpt-5.4",
model="gpt-5.6-sol",
handoffs=[spanish_agent],
tools=[get_weather],
)
@@ -195,4 +195,4 @@ if __name__ == "__main__":
asyncio.run(main())
```
この example を実行すると、エージェントがあなたに話しかけます。[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static) の example では、自分でエージェントに話しかけられるデモを確認できます
このを実行すると、エージェントが話しかけてきます!自分でエージェントに話しかけられるデモについては、[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static) の例をご覧ください
+7 -7
View File
@@ -4,15 +4,15 @@ search:
---
# トレーシング
[エージェントトレーシングされる](../tracing.md)と同様に、音声パイプラインも自動的にトレーシングされます。
[エージェントトレーシング](../tracing.md)と同様に、音声パイプラインも自動的にトレーシングされます。
基本的なトレーシング情報については上記のトレーシングドキュメントを参照できますが、[`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig] を介してパイプラインのトレーシングを追加で設定することもできます。
基本的なトレーシング情報については上記のトレーシングドキュメントを参照できますが、さらに [`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig] を通じてパイプラインのトレーシングを設定できます。
トレーシングに関連する主なフィールドは次のとおりです。
トレーシングに関連する主なフィールドは次のとおりです。
- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレーシングを無効するかどうかを制御します。デフォルトでは、トレーシングは有効です。
- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: トレースに音声文字起こしのような潜在的に機微なデータを含めるかどうかを制御します。これは音声パイプライン専用であり、Workflow 内で行われるものには適用されません。
- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレーシングを無効するかどうかを制御します。デフォルトでは、トレーシングは有効です。
- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: トレースに音声文字起こしなど、潜在的に機微なデータを含めるかどうかを制御します。これは音声パイプライン専用であり、Workflow 内で行われる処理には適用されません。
- [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]: トレースに音声データを含めるかどうかを制御します。
- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: トレース Workflow の名前です。
- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: トレースの `group_id` で、複数のトレースを関連付けられます。
- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: トレースワークフローの名前です。
- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: トレースの `group_id` で、複数のトレースを関連付けることができます。
- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.trace_metadata]: トレースに含める追加のメタデータです。
+81 -76
View File
@@ -4,46 +4,49 @@ search:
---
# 에이전트
에이전트는 앱의 핵심 구성 요소입니다. 에이전트는 instructions, tools, 그리고 핸드오프, 가드레일, structured outputs 같은 선택적 런타임 동작으로 구성된 대규모 언어 모델( LLM )입니다
에이전트는 앱의 핵심 구성 요소입니다. 에이전트는 instructions, tools, 그리고 핸드오프, 가드레일, structured outputs 같은 선택적 런타임 동작으로 구성된 대규모 언어 모델(LLM)입니다.
단일 에이전트를 정의하거나 사용자 지정하려면 이 페이지를 사용하세요. 여러 에이전트가 어떻게 협업해야 할지 결정 중이라면 [에이전트 오케스트레이션](multi_agent.md)을 읽어보세요
하나의 일반 `Agent`를 정의하거나 사용자 지정하려면 이 페이지를 사용하세요. 여러 에이전트가 협업하는 방식을 결정하려면 [에이전트 오케스트레이션](multi_agent.md)을 읽어보세요. 에이전트가 매니페스트에 정의된 파일과 샌드박스 네이티브 기능을 갖춘 격리된 워크스페이스 내에서 실행되어야 한다면 [샌드박스 에이전트 개념](sandbox/guide.md)을 읽어보세요.
SDK는 OpenAI 모델에 기본적으로 Responses API를 사용하지만, 여기서 중요한 차이는 오케스트레이션입니다. `Agent``Runner`를 함께 사용하면 SDK가 턴, 도구, 가드레일, 핸드오프, 세션을 대신 관리합니다. 이 루프를 직접 관리하려면 Responses API를 직접 사용하세요.
## 다음 가이드 선택
이 페이지를 에이전트 정의 허브로 사용하세요. 다음으로 내려야 할 결정에 는 인접 가이드로 이동하세요
이 페이지를 에이전트 정의를 위한 허브로 사용하세요. 다음으로 내려야 할 결정에 해당하는 인접 가이드로 이동하세요.
| 원하는 작업 | 다음 읽을 내용 |
| 원하는 작업 | 다음으로 읽을 문서 |
| --- | --- |
| 모델 또는 provider 설정 선택 | [모델](models/index.md) |
| 모델 또는 제공자 설정 선택 | [모델](models/index.md) |
| 에이전트에 기능 추가 | [도구](tools.md) |
| 매니저 스타일 오케스트레이션과 핸드오프 중 선택 | [에이전트 오케스트레이션](multi_agent.md) |
| 실제 저장소, 문서 번들 또는 격리된 워크스페이스에서 에이전트 실행 | [샌드박스 에이전트 빠른 시작](sandbox_agents.md) |
| 관리자 방식 오케스트레이션과 핸드오프 중 선택 | [에이전트 오케스트레이션](multi_agent.md) |
| 핸드오프 동작 구성 | [핸드오프](handoffs.md) |
| 턴 실행, 이벤트 스트리밍, 대화 상태 관리 | [에이전트 실행](running_agents.md) |
| 최종 출력, 실행 항목, 재개 가능한 상태 검 | [결과](results.md) |
| 로컬 의존성 및 런타임 상태 공유 | [컨텍스트 관리](context.md) |
| 턴 실행, 이벤트 스트리밍 또는 대화 상태 관리 | [에이전트 실행](running_agents.md) |
| 최종 출력, 실행 항목 또는 재개 가능한 상태 검 | [결과](results.md) |
| 로컬 종속성과 런타임 상태 공유 | [컨텍스트 관리](context.md) |
## 기본 구성
에이전트의 가장 일반적인 속성은 다음과 같습니다
에이전트의 가장 일반적인 속성은 다음과 같습니다.
| 속성 | 필수 | 설명 |
| 속성 | 필수 여부 | 설명 |
| --- | --- | --- |
| `name` | yes | 사람이 읽을 수 있는 에이전트 이름 |
| `instructions` | yes | 시스템 프롬프트 또는 동적 instructions 콜백. [동적 instructions](#dynamic-instructions) 참 |
| `prompt` | no | OpenAI Responses API 프롬프트 구성. 정적 프롬프트 객체 또는 함수를 허용합니다. [프롬프트 템플릿](#prompt-templates) 참 |
| `handoff_description` | no | 이 에이전트가 핸드오프 대상으로 제될 때 노출되는 짧은 설명 |
| `handoffs` | no | 대화를 전문 에이전트에 위임합니다. [handoffs](handoffs.md) 참 |
| `model` | no | 사용할 LLM. [모델](models/index.md) 참 |
| `model_settings` | no | `temperature`, `top_p`, `tool_choice` 같은 모델 튜닝 매개변수 |
| `tools` | no | 에이전트가 호출할 수 있는 도구. [도구](tools.md) 참 |
| `mcp_servers` | no | 에이전트를 위한 MCP 기반 도구. [MCP 가이드](mcp.md) 참 |
| `mcp_config` | no | strict 스키마 변환 MCP 실패 포맷팅처럼 MCP 도구 준비 방식을 세부 조정합니다. [MCP 가이드](mcp.md#agent-level-mcp-configuration) 참 |
| `input_guardrails` | no | 이 에이전트 체인의 첫 사용자 입력에 실행되는 가드레일. [가드레일](guardrails.md) 참 |
| `output_guardrails` | no | 이 에이전트의 최종 출력에 실행되는 가드레일. [가드레일](guardrails.md) 참 |
| `output_type` | no | 일반 텍스트 대신 구조화된 출력 타입. [출력 타입](#output-types) 참 |
| `hooks` | no | 에이전트 범위의 라이프사이클 콜백. [라이프사이클 이벤트 (hooks)](#lifecycle-events-hooks) 참 |
| `tool_use_behavior` | no | 도구 결과를 모델로 다시 보낼지, 실행을 종료할지 제어합니다. [도구 사용 동작](#tool-use-behavior) 참 |
| `reset_tool_choice` | no | 도구 호출 후 `tool_choice` 재설정(기본값: `True`)으로 도구 사용 루프를 방지합니다. [도구 사용 강제](#forcing-tool-use) 참 |
| `name` | | 사람이 읽을 수 있는 에이전트 이름입니다. |
| `instructions` | 아니요 | 시스템 프롬프트 또는 동적 instructions 콜백입니다. 사용을 강력히 권장합니다. [동적 instructions](#dynamic-instructions)조하세요. |
| `prompt` | 아니요 | OpenAI Responses API 프롬프트 구성입니다. 정적 프롬프트 객체 또는 함수를 허용합니다. [프롬프트 템플릿](#prompt-templates)조하세요. |
| `handoff_description` | 아니요 | 이 에이전트가 핸드오프 대상으로 제될 때 노출되는 간단한 설명입니다. |
| `handoffs` | 아니요 | 대화를 전문 에이전트에 위임합니다. [핸드오프](handoffs.md)조하세요. |
| `model` | 아니요 | 사용할 LLM입니다. [모델](models/index.md)조하세요. |
| `model_settings` | 아니요 | `temperature`, `top_p`, `tool_choice` 같은 모델 조정 매개변수입니다. |
| `tools` | 아니요 | 에이전트가 호출할 수 있는 도구입니다. [도구](tools.md)조하세요. |
| `mcp_servers` | 아니요 | 에이전트 MCP 기반 도구입니다. [MCP 가이드](mcp.md)조하세요. |
| `mcp_config` | 아니요 | 엄격한 스키마 변환 MCP 실패 형식 지정 등 MCP 도구 준비되는 방식을 세부 조정합니다. [MCP 가이드](mcp.md#agent-level-mcp-configuration)조하세요. |
| `input_guardrails` | 아니요 | 이 에이전트 체인의 첫 번째 사용자 입력에 대해 실행되는 가드레일입니다. [가드레일](guardrails.md)조하세요. |
| `output_guardrails` | 아니요 | 이 에이전트의 최종 출력에 대해 실행되는 가드레일입니다. [가드레일](guardrails.md)조하세요. |
| `output_type` | 아니요 | 일반 텍스트 대신 사용하는 structured outputs 타입입니다. [출력 타입](#output-types)조하세요. |
| `hooks` | 아니요 | 에이전트 범위의 수명 주기 콜백입니다. [수명 주기 이벤트(훅)](#lifecycle-events-hooks)조하세요. |
| `tool_use_behavior` | 아니요 | 도구 결과를 다시 모델로 전달할지, 아니면 실행을 종료할지 제어합니다. [도구 사용 동작](#tool-use-behavior)조하세요. |
| `reset_tool_choice` | 아니요 | 도구 사용 루프를 방지하기 위해 도구 호출 후 `tool_choice` 재설정합니다(기본값: `True`). [도구 사용 강제](#forcing-tool-use)조하세요. |
```python
from agents import Agent, ModelSettings, function_tool
@@ -61,21 +64,23 @@ agent = Agent(
)
```
이 섹션의 모든 내용은 `Agent`에 적용됩니다. `SandboxAgent`는 동일한 개념을 기반으로 하며, 워크스페이스 범위 실행을 위한 `default_manifest`, `base_instructions`, `capabilities`, `run_as`를 추가합니다. [샌드박스 에이전트 개념](sandbox/guide.md)을 참조하세요.
## 프롬프트 템플릿
`prompt`를 설정하 OpenAI 플랫폼에서 만든 프롬프트 템플릿을 참조할 수 있습니다. 이 Responses API를 사용하는 OpenAI 모델에서 작합니다
`prompt`를 설정하 OpenAI 플랫폼에서 생성한 프롬프트 템플릿을 참조할 수 있습니다. 이 기능은 Responses API를 사용하는 OpenAI 모델에서 작합니다.
사용 방법:
사용 방법은 다음과 같습니다.
1. https://platform.openai.com/playground/prompts 로 이동
2. 새 프롬프트 변수 `poem_style` 생성
3. 다음 내용으로 시스템 프롬프트 생성:
1. https://platform.openai.com/playground/prompts 로 이동합니다
2. 새 프롬프트 변수 `poem_style` 생성합니다
3. 다음 내용으로 시스템 프롬프트 생성합니다.
```
Write a poem in {{poem_style}}
```
4. `--prompt-id` 플래그 예제 실행
4. `--prompt-id` 플래그를 사용하여 예제 실행합니다.
```python
from agents import Agent
@@ -90,7 +95,7 @@ agent = Agent(
)
```
실행 시점에 프롬프트를 동적으로 생성할 수도 있습니다
런타임에 프롬프트를 동적으로 생성할 수도 있습니다.
```python
from dataclasses import dataclass
@@ -122,9 +127,9 @@ result = await Runner.run(
## 컨텍스트
에이전트는 `context` 타입에 대해 제네릭니다. 컨텍스트는 의존성 주입 도구입니다. 즉, 사용자가 생성해 `Runner.run()`에 전달하는 객체로, 모든 에이전트, 도구, 핸드오프 등에 전달되며 에이전트 실행을 위한 의존성과 상태를 담는 모음 역할을 합니다. 컨텍스트로는 어떤 Python 객체든 제공할 수 있습니다
에이전트는 `context` 타입에 대해 제네릭니다. 컨텍스트는 종속성 주입 도구입니다. 직접 객체를 생성해 `Runner.run()`에 전달하 모든 에이전트, 도구, 핸드오프 등에 전달되며, 에이전트 실행에 필요한 종속성과 상태를 담는 컨테이너 역할을 합니다. 어떤 Python 객체든 컨텍스트로 제공할 수 있습니다.
전체 `RunContextWrapper` 표면, 공유 사용량 추적, 중첩 `tool_input`, 직렬화 관련 주의사항은 [컨텍스트 가이드](context.md)를 읽어보세요
전체 `RunContextWrapper` 인터페이스, 공유 사용량 추적, 중첩 `tool_input`, 직렬화 주의 사항은 [컨텍스트 가이드](context.md)를 참조하세요.
```python
@dataclass
@@ -143,7 +148,7 @@ agent = Agent[UserContext](
## 출력 타입
기본적으로 에이전트는 일반 텍스트(즉 `str`) 출력을 생성합니다. 에이전트가 특정 타입의 출력을 생성하도록 하려면 `output_type` 매개변수를 사용할 수 있습니다. 일반적으로 [Pydantic](https://docs.pydantic.dev/) 객체를 많이 사용하지만, Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/)로 래핑 가능한 타입은 모두 지원합니다 - dataclasses, lists, TypedDict 등
기본적으로 에이전트는 일반 텍스트(즉, `str`) 출력을 생성합니다. 에이전트가 특정 타입의 출력을 생성하도록 하려면 `output_type` 매개변수를 사용할 수 있습니다. 일반적으로 [Pydantic](https://docs.pydantic.dev/) 객체를 사용하지만, Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/)로 래핑할 수 있는 모든 타입(dataclass, 리스트, TypedDict 등)을 지원합니다.
```python
from pydantic import BaseModel
@@ -164,20 +169,20 @@ agent = Agent(
!!! note
`output_type`을 전달하면, 모델은 일반 텍스트 응답 대신 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)을 사용하도록 지시받습니다
`output_type`을 전달하면 모델은 일반적인 일반 텍스트 응답 대신 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)을 사용니다.
## 멀티 에이전트 시스템 설계 패턴
멀티 에이전트 시스템 설계 방법은 다양하지만, 일반적으로 널리 적용 가능한 두 가지 패턴이 있습니다:
멀티 에이전트 시스템 설계하는 방법은 다양하지만, 일반적으로 폭넓게 적용할 수 있는 다음 두 가지 패턴이 사용됩니다.
1. 매니저(Agents as tools): 중앙 매니저/오케스트레이터가 전문 하위 에이전트를 도구로 호출하고 대화 제어 유지합니다
2. 핸드오프: 동 에이전트가 제어를 전문 에이전트 넘기고, 해당 에이전트가 대화를 이어받습니다. 분산형 방식입니다
1. 관리자(agents as tools): 중앙 관리자/오케스트레이터가 전문화된 하위 에이전트를 도구로 호출하고 대화에 대한 제어권을 유지합니다.
2. 핸드오프: 동등한 에이전트가 대화 제어권을 전문 에이전트에게 넘기고, 해당 에이전트가 대화를 이어받습니다. 이는 분산형 방식입니다.
자세한 내용은 [에이전트 구축 실전 가이드](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)를 참하세요
자세한 내용은 [에이전트 구축 실전 가이드](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)를 참하세요.
### 매니저(Agents as tools)
### 관리자(agents as tools)
`customer_facing_agent`는 모든 사용자 상호작용을 처리하고 도구로 노출된 전문 하위 에이전트를 호출합니다. 자세한 내용은 [tools](tools.md#agents-as-tools) 문서를 참하세요
`customer_facing_agent`는 모든 사용자 상호작용을 처리하고 도구로 노출된 전문화된 하위 에이전트를 호출합니다. 자세한 내용은 [도구](tools.md#agents-as-tools) 문서를 참하세요.
```python
from agents import Agent
@@ -206,7 +211,7 @@ customer_facing_agent = Agent(
### 핸드오프
핸드오프는 에이전트가 위임할 수 있는 하위 에이전트입니다. 핸드오프가 발생하면 위임 에이전트가 대화 기록을 받아 대화를 이어받습니다. 이 패턴은 단일 작업에 뛰어난 모듈식 전문 에이전트를 가능하게 합니다. 자세한 내용은 [handoffs](handoffs.md) 문서를 참하세요
핸드오프는 에이전트가 작업을 위임할 수 있는 하위 에이전트입니다. 핸드오프가 발생하면 위임받은 에이전트가 대화 기록을 전달받고 대화를 이어받습니다. 이 패턴을 사용하면 하나의 작업에 특화된 모듈식 전문 에이전트를 구성할 수 있습니다. 자세한 내용은 [핸드오프](handoffs.md) 문서를 참하세요.
```python
from agents import Agent
@@ -227,7 +232,7 @@ triage_agent = Agent(
## 동적 instructions
대부분의 경우 에이전트를 생성할 때 instructions를 제공하면 됩니다. 하지만 함수를 통해 동적 instructions를 제공할 수도 있습니다. 함수는 에이전트와 컨텍스트를 전달받아 프롬프트를 반환해야 합니다. 일반 함수와 `async` 함수 모두 허용됩니다
대부분의 경우 에이전트를 생성할 때 instructions를 제공할 수 있습니다. 하지만 함수를 통해 동적 instructions를 제공할 수도 있습니다. 함수는 에이전트와 컨텍스트를 전달받아 프롬프트를 반환해야 합니다. 일반 함수와 `async` 함수 모두 허용됩니다.
```python
def dynamic_instructions(
@@ -242,28 +247,28 @@ agent = Agent[UserContext](
)
```
## 라이프사이클 이벤트 (hooks)
## 수명 주기 이벤트(훅)
때로는 에이전트의 라이프사이클을 관찰하고 싶을 수 있습니다. 예를 들어 이벤트 로깅, 데이터 사전 로드, 특정 이벤트 발생 시 사용량 기록 등을 원할 수 있습니다
경우에 따라 에이전트의 수명 주기를 관찰해야 할 수 있습니다. 예를 들어 특정 이벤트가 발생할 때 이벤트를 기록하거나, 데이터를 미리 가져오거나, 사용량 기록할 수 있습니다.
hook 범위는 두 가지입니다:
훅의 범위는 두 가지입니다.
- [`RunHooks`][agents.lifecycle.RunHooks]는 다른 에이전트로의 핸드오프를 포함해 전체 `Runner.run(...)` 호출을 관찰합니다
- [`AgentHooks`][agents.lifecycle.AgentHooks]는 `agent.hooks`를 통해 특정 에이전트 인스턴스에 연결됩니다
- [`RunHooks`][agents.lifecycle.RunHooks]는 다른 에이전트로의 핸드오프를 포함해 전체 `Runner.run(...)` 호출을 관찰합니다.
- [`AgentHooks`][agents.lifecycle.AgentHooks]는 `agent.hooks`를 통해 특정 에이전트 인스턴스에 연결됩니다.
콜백 컨텍스트도 이벤트에 따라 달라집니다:
콜백 컨텍스트도 이벤트에 따라 달라집니다.
- 에이전트 시작/종료 hook은 [`AgentHookContext`][agents.run_context.AgentHookContext]를 받으며, 이는 원 컨텍스트를 래핑하 공유 실행 사용량 상태를 담습니다
- LLM, 도구, 핸드오프 hook은 [`RunContextWrapper`][agents.run_context.RunContextWrapper]를 받습니다
- 에이전트 시작/종료 은 [`AgentHookContext`][agents.run_context.AgentHookContext]를 전달받습니다. 이 컨텍스트는 원 컨텍스트를 래핑하 공유 실행 사용량 상태를 포함합니다.
- LLM, 도구, 핸드오프 은 [`RunContextWrapper`][agents.run_context.RunContextWrapper]를 전달받습니다.
일반적인 hook 시점:
일반적인 훅 실행 시점은 다음과 같습니다.
- `on_agent_start` / `on_agent_end`: 특정 에이전트가 최종 출력 생성을 시작하거나 마칠
- `on_llm_start` / `on_llm_end`: 각 모델 호출 직전/직후
- `on_tool_start` / `on_tool_end`: 각 로컬 도구 호출 전후
- `on_handoff`: 제어 한 에이전트에서 다른 에이전트로 이동할 때
- `on_agent_start` / `on_agent_end`: 특정 에이전트가 최종 출력 생성을 시작하거나 완료할
- `on_llm_start` / `on_llm_end`: 각 모델 호출 직전직후
- `on_tool_start` / `on_tool_end`: 각 로컬 도구 호출 전후. 함수 도구의 경우 훅 `context`는 일반적으로 `ToolContext`이므로 `tool_call_id` 같은 도구 호출 메타데이터를 검사할 수 있습니다.
- `on_handoff`: 제어권이 한 에이전트에서 다른 에이전트로 이동할 때
전체 워크플로를 단일 관찰자로 보고 싶다`RunHooks`를, 특정 에이전트에 맞춤 부수 효과가 필요하면 `AgentHooks`를 사용하세요
전체 워크플로를 위한 단일 관찰자가 필요하`RunHooks` 사용하고, 특정 에이전트에 사용자 지정 부수 효과가 필요하면 `AgentHooks`를 사용하세요.
```python
from agents import Agent, RunHooks, Runner
@@ -285,21 +290,21 @@ result = await Runner.run(agent, "Explain quines", hooks=LoggingHooks())
print(result.final_output)
```
전체 콜백 표면은 [라이프사이클 API 레퍼런스](ref/lifecycle.md)를 참하세요
전체 콜백 인터페이스는 [수명 주기 API 레퍼런스](ref/lifecycle.md)를 참하세요.
## 가드레일
가드레일을 사용하면 에이전트 실행과 병렬로 사용자 입력에 대한 검사/검증을 행하고, 에이전트 출력이 생성된 뒤 출력에 대한 검사도 수행할 수 있습니다. 예를 들어 사용자 입력과 에이전트 출력의 관련성을 검사할 수 있습니다. 자세한 내용은 [guardrails](guardrails.md) 문서를 참하세요
가드레일을 사용하면 에이전트 실행과 병렬로 사용자 입력에 대한 검사/검증을 행하고, 에이전트 출력이 생성된 후 해당 출력도 검사할 수 있습니다. 예를 들어 사용자 입력과 에이전트 출력의 관련성을 검사할 수 있습니다. 자세한 내용은 [가드레일](guardrails.md) 문서를 참하세요.
## 에이전트 복제/복사
에이전트의 `clone()` 메서드를 사용하면 Agent를 복제하고, 원하는 속성을 선택적으로 변경할 수 있습니다
에이전트의 `clone()` 메서드를 사용하면 에이전트를 복제하고 원하는 속성을 선택적으로 변경할 수 있습니다.
```python
pirate_agent = Agent(
name="Pirate",
instructions="Write like a pirate",
model="gpt-5.4",
model="gpt-5.6-sol",
)
robot_agent = pirate_agent.clone(
@@ -310,14 +315,14 @@ robot_agent = pirate_agent.clone(
## 도구 사용 강제
도구 목록을 제공다고 해서 항상 LLM이 도구를 사용하는 것은 아닙니다. [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice]를 설정 도구 사용을 강제할 수 있습니다. 유효한 값은 다음과 같습니다:
도구 목록을 제공다고 해서 LLM이 항상 도구를 사용하는 것은 아닙니다. [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice]를 설정하여 도구 사용을 강제할 수 있습니다. 유효한 값은 다음과 같습니다.
1. `auto`: LLM이 도구 사용 여부를 결정
2. `required`: LLM이 도구를 반드시 사용(어떤 도구를 쓸지는 합리적으로 결정 가능)
3. `none`: LLM이 도구를 사용하지 않
4. 특정 문자열(예: `my_tool`) 설정: LLM이 해당 도구를 반드시 사용
1. `auto`: LLM이 도구 사용 여부를 결정할 수 있습니다.
2. `required`: LLM이 도구를 반드시 사용해야 합니다. 단, 사용할 도구는 지능적으로 결정할 수 있습니다.
3. `none`: LLM이 도구를 _사용하지 않도록_ 합니다.
4. `my_tool` 같은 특정 문자열: LLM이 해당 도구를 반드시 사용하도록 합니다.
OpenAI Responses 도구 검색을 사용할 때는 이름 지정 도구 선택에 더 많은 제이 있습니다: `tool_choice` 단순 네임스페이스 이름이나 deferred-only 도구를 대상으로 지정할 수 없, `tool_choice="tool_search"`는 [`ToolSearchTool`][agents.tool.ToolSearchTool]을 대상으로 하지 않습니다. 이런 경우 `auto` 또는 `required`권장합니다. Responses 전용 제약사항은 [호스티드 도구 검색](tools.md#hosted-tool-search)을 참하세요
OpenAI Responses 도구 검색을 사용할 때는 지정 도구 선택에 더 많은 제이 있습니다. `tool_choice`로 네임스페이스 이름 자체나 지연 전용 도구를 지정할 수 없으며, `tool_choice="tool_search"`는 [`ToolSearchTool`][agents.tool.ToolSearchTool]을 대상으로 하지 않습니다. 이런 경우에는 `auto` 또는 `required`사용하는 것이 좋습니다. Responses 관련 제약은 [호스티드 검색](tools.md#hosted-tool-search)을 참하세요.
```python
from agents import Agent, Runner, function_tool, ModelSettings
@@ -337,10 +342,10 @@ agent = Agent(
## 도구 사용 동작
`Agent` 구성의 `tool_use_behavior` 매개변수는 도구 출력 처리 방식을 제어합니다:
`Agent` 구성의 `tool_use_behavior` 매개변수는 도구 출력 처리 방식을 제어합니다.
- `"run_llm_again"`: 기본값. 도구를 실행한 뒤, LLM이 결과를 처리 최종 응답 생성
- `"stop_on_first_tool"`: 첫 번째 도구 호출의 출력을 추가 LLM 처리 없이 최종 응답으로 사용
- `"run_llm_again"`: 기본값입니다. 도구를 실행한 LLM이 결과를 처리하여 최종 응답 생성합니다.
- `"stop_on_first_tool"`: 추가 LLM 처리 없이 첫 번째 도구 호출의 출력을 최종 응답으로 사용합니다.
```python
from agents import Agent, Runner, function_tool, ModelSettings
@@ -358,7 +363,7 @@ agent = Agent(
)
```
- `StopAtTools(stop_at_tool_names=[...])`: 지정 도구 중 하나라도 호출되면 중지하고, 해당 출력을 최종 응답으로 사용
- `StopAtTools(stop_at_tool_names=[...])`: 지정 도구 중 하나라도 호출되면 중지하고 해당 출력을 최종 응답으로 사용합니다.
```python
from agents import Agent, Runner, function_tool
@@ -382,7 +387,7 @@ agent = Agent(
)
```
- `ToolsToFinalOutputFunction`: 도구 결과를 처리하고 LLM으로 계속 진행할지 중지할지 결정하는 사용자 지정 함수
- `ToolsToFinalOutputFunction`: 도구 결과를 처리하고 LLM을 중지할지 계속 실행할지 결정하는 사용자 지정 함수입니다.
```python
from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper
@@ -420,4 +425,4 @@ agent = Agent(
!!! note
무한 루프를 방지하기 위해 프레임워크는 도구 호출 후 `tool_choice`를 자동으로 "auto"로 재설정합니다. 이 동작은 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] 구성할 수 있습니다. 무한 루프가 발생하는 이유는 도구 결과가 LLM으로 전송되고, `tool_choice` 때문에 LLM이 다시 도구 호출을 생성하 과정이 무한 반복되기 때문입니다
무한 루프를 방지하기 위해 프레임워크는 도구 호출 후 `tool_choice`를 자동으로 "auto"로 재설정합니다. 이 동작은 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice]를 통해 구성할 수 있습니다. 무한 루프가 발생하는 이유는 도구 결과가 LLM으로 전송된 후 `tool_choice`로 인해 LLM이 다시 도구 호출을 생성하며 이 과정이 끝없이 반복되기 때문입니다.

Some files were not shown because too many files have changed in this diff Show More