handoffkit 1.2.0__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. {handoffkit-1.2.0/handoffkit.egg-info → handoffkit-1.4.0}/PKG-INFO +170 -4
  2. {handoffkit-1.2.0 → handoffkit-1.4.0}/README.md +169 -3
  3. handoffkit-1.4.0/examples/doctor_benchmark.py +7 -0
  4. handoffkit-1.4.0/examples/doctor_orchestrator.py +13 -0
  5. handoffkit-1.4.0/examples/mai_clinical_ensemble_benchmark.py +738 -0
  6. handoffkit-1.4.0/examples/mai_clinical_mimo_benchmark.py +861 -0
  7. handoffkit-1.4.0/examples/mai_clinical_mimo_rescue.py +231 -0
  8. handoffkit-1.4.0/examples/mai_clinical_targeted_rescue.py +990 -0
  9. handoffkit-1.4.0/examples/mai_style_doctor_benchmark.py +7 -0
  10. handoffkit-1.4.0/examples/medical_tools_demo.py +33 -0
  11. handoffkit-1.4.0/examples/opencode_go_agent.py +65 -0
  12. handoffkit-1.4.0/examples/opencode_zen_agent.py +66 -0
  13. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/__init__.py +6 -1
  14. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/cli.py +201 -2
  15. handoffkit-1.4.0/handoffkit/doctor_benchmark.py +414 -0
  16. handoffkit-1.4.0/handoffkit/doctor_cases_100.py +1212 -0
  17. handoffkit-1.4.0/handoffkit/doctor_cases_30.py +12 -0
  18. handoffkit-1.4.0/handoffkit/doctor_cases_400.py +4812 -0
  19. handoffkit-1.4.0/handoffkit/mai_benchmark.py +605 -0
  20. handoffkit-1.4.0/handoffkit/providers/__init__.py +61 -0
  21. handoffkit-1.4.0/handoffkit/providers/opencode_provider.py +401 -0
  22. handoffkit-1.4.0/handoffkit/providers/registry.py +316 -0
  23. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/showcases.py +194 -1
  24. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/templates.py +13 -0
  25. handoffkit-1.4.0/handoffkit/tool_factory.py +183 -0
  26. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tools/__init__.py +10 -0
  27. handoffkit-1.4.0/handoffkit/tools/medical.py +219 -0
  28. {handoffkit-1.2.0 → handoffkit-1.4.0/handoffkit.egg-info}/PKG-INFO +170 -4
  29. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit.egg-info/SOURCES.txt +28 -0
  30. {handoffkit-1.2.0 → handoffkit-1.4.0}/pyproject.toml +1 -1
  31. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_api_stability.py +2 -2
  32. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_cli.py +89 -3
  33. handoffkit-1.4.0/tests/test_clinical_benchmark_audit.py +69 -0
  34. handoffkit-1.4.0/tests/test_clinical_ensemble_benchmark.py +45 -0
  35. handoffkit-1.4.0/tests/test_clinical_targeted_rescue.py +98 -0
  36. handoffkit-1.4.0/tests/test_doctor_benchmark.py +57 -0
  37. handoffkit-1.4.0/tests/test_mai_benchmark.py +64 -0
  38. handoffkit-1.4.0/tests/test_medical_tools.py +167 -0
  39. handoffkit-1.4.0/tests/test_opencode_provider_mock.py +287 -0
  40. handoffkit-1.4.0/tests/test_provider_registry.py +135 -0
  41. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_public_api_compatibility.py +4 -0
  42. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_showcases.py +10 -2
  43. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_stable_metadata.py +2 -2
  44. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_templates.py +1 -0
  45. handoffkit-1.4.0/tests/test_tool_factory.py +73 -0
  46. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_wheel_smoke.py +1 -1
  47. handoffkit-1.2.0/handoffkit/providers/__init__.py +0 -21
  48. {handoffkit-1.2.0 → handoffkit-1.4.0}/LICENSE +0 -0
  49. {handoffkit-1.2.0 → handoffkit-1.4.0}/MANIFEST.in +0 -0
  50. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/async_demo.py +0 -0
  51. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/coding_review.py +0 -0
  52. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/coding_review_recipe.py +0 -0
  53. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/coding_team.py +0 -0
  54. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/context_handoff_demo.py +0 -0
  55. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/contract_validation_demo.py +0 -0
  56. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/evaluation_demo.py +0 -0
  57. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/extension_demo.py +0 -0
  58. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/fake_provider_tool_call_demo.py +0 -0
  59. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/freemodel_best_model_demo.py +0 -0
  60. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/freemodel_coding_team.py +0 -0
  61. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/freemodel_openai_compatible.py +0 -0
  62. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/handoff_demo.py +0 -0
  63. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/handoff_quality_demo.py +0 -0
  64. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/langgraph_integration.py +0 -0
  65. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/memory_demo.py +0 -0
  66. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/ollama_agent.py +0 -0
  67. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/openai_agents_sdk_integration.py +0 -0
  68. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/project_context_demo.py +0 -0
  69. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/provider_matrix_demo.py +0 -0
  70. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/provider_tool_adapter_demo.py +0 -0
  71. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/provider_tool_formats_demo.py +0 -0
  72. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/pydantic_ai_integration.py +0 -0
  73. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/real_task_calculator.py +0 -0
  74. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/recipe_demo.py +0 -0
  75. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/replay_demo.py +0 -0
  76. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/repo_inspired_protocols.py +0 -0
  77. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/research_workflow.py +0 -0
  78. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/simple_agent.py +0 -0
  79. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/structured_output_demo.py +0 -0
  80. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/structured_recipe_demo.py +0 -0
  81. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/support_escalation.py +0 -0
  82. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/template_demo.py +0 -0
  83. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/tool_agent.py +0 -0
  84. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/tool_execution_demo.py +0 -0
  85. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/tool_schema_demo.py +0 -0
  86. {handoffkit-1.2.0 → handoffkit-1.4.0}/examples/trace_demo.py +0 -0
  87. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/agent.py +0 -0
  88. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/builtins.py +0 -0
  89. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/context.py +0 -0
  90. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/errors.py +0 -0
  91. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/evaluation.py +0 -0
  92. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/extensions.py +0 -0
  93. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/handoff.py +0 -0
  94. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/memory.py +0 -0
  95. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocol.py +0 -0
  96. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocols/__init__.py +0 -0
  97. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocols/compressed.py +0 -0
  98. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocols/hybrid_min.py +0 -0
  99. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocols/hybrid_state.py +0 -0
  100. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/protocols/natural.py +0 -0
  101. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/provider_adapters.py +0 -0
  102. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/providers/base.py +0 -0
  103. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/providers/echo_provider.py +0 -0
  104. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/providers/ollama_provider.py +0 -0
  105. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/providers/openai_compatible.py +0 -0
  106. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/providers/openai_provider.py +0 -0
  107. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/py.typed +0 -0
  108. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/quality.py +0 -0
  109. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/recipes.py +0 -0
  110. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/replay.py +0 -0
  111. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/reports.py +0 -0
  112. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/runner.py +0 -0
  113. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/safety.py +0 -0
  114. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/schemas.py +0 -0
  115. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/structured.py +0 -0
  116. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tool.py +0 -0
  117. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tool_execution.py +0 -0
  118. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tools/filesystem.py +0 -0
  119. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tools/shell.py +0 -0
  120. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tools/text.py +0 -0
  121. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/tracing.py +0 -0
  122. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit/validation.py +0 -0
  123. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit.egg-info/dependency_links.txt +0 -0
  124. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit.egg-info/entry_points.txt +0 -0
  125. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit.egg-info/requires.txt +0 -0
  126. {handoffkit-1.2.0 → handoffkit-1.4.0}/handoffkit.egg-info/top_level.txt +0 -0
  127. {handoffkit-1.2.0 → handoffkit-1.4.0}/setup.cfg +0 -0
  128. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_070_examples.py +0 -0
  129. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_adoption_docs.py +0 -0
  130. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_agent.py +0 -0
  131. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_async_runtime.py +0 -0
  132. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_cli_doctor.py +0 -0
  133. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_coding_team.py +0 -0
  134. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_contract_validation.py +0 -0
  135. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_docs_090.py +0 -0
  136. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_evaluation.py +0 -0
  137. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_handoff.py +0 -0
  138. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_imports.py +0 -0
  139. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_json_schemas.py +0 -0
  140. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_memory_context.py +0 -0
  141. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_ollama_provider_mock.py +0 -0
  142. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_openai_model_selection.py +0 -0
  143. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_openai_provider_mock.py +0 -0
  144. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_protocols.py +0 -0
  145. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_provider_adapters.py +0 -0
  146. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_provider_matrix.py +0 -0
  147. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_quality.py +0 -0
  148. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_real_task_demo.py +0 -0
  149. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_recipes_extensions.py +0 -0
  150. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_release_process_docs.py +0 -0
  151. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_replay.py +0 -0
  152. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_reports.py +0 -0
  153. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_shell_safety.py +0 -0
  154. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_structured_outputs.py +0 -0
  155. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_team.py +0 -0
  156. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_tool.py +0 -0
  157. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_tool_execution.py +0 -0
  158. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_tracing.py +0 -0
  159. {handoffkit-1.2.0 → handoffkit-1.4.0}/tests/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: handoffkit
3
- Version: 1.2.0
3
+ Version: 1.4.0
4
4
  Summary: A lightweight Python framework for building multi-agent workflows with structured state transfer protocols.
5
5
  Author: DaosPath
6
6
  License-Expression: MIT
@@ -30,7 +30,7 @@ Requires-Dist: twine>=6.0.0; extra == "dev"
30
30
  Requires-Dist: wheel; extra == "dev"
31
31
  Dynamic: license-file
32
32
 
33
- <div align="center">
33
+ <div align="center">
34
34
 
35
35
  <img src="https://raw.githubusercontent.com/DaosPath/handoffkit/main/docs/assets/handoffkit-hero.svg" alt="HandoffKit: structured state transfer for multi-agent Python workflows" width="100%">
36
36
 
@@ -125,6 +125,44 @@ replay evidence stay attached to the work.
125
125
 
126
126
  <img src="https://raw.githubusercontent.com/DaosPath/handoffkit/main/docs/assets/handoffkit-report-gallery.svg" alt="HandoffKit report gallery for coding agents, support escalation, and research workflow" width="100%">
127
127
 
128
+ Bonus educational healthcare workflow:
129
+
130
+ ```bash
131
+ handoffkit showcase doctor-orchestrator
132
+ handoffkit report runs/latest
133
+ ```
134
+
135
+ `doctor-orchestrator` is a synthetic demo inspired by virtual physician-panel
136
+ orchestration patterns: Intake -> Hypothesis -> Challenger -> Test Steward ->
137
+ Checklist -> Final Reviewer. It demonstrates structured uncertainty, missing
138
+ questions, red-flag tracking, cost-aware test reasoning, and replayable review
139
+ evidence. It is not medical advice.
140
+
141
+ Real open-access case benchmark preview:
142
+
143
+ ```bash
144
+ handoffkit benchmark-doctor --cases 30
145
+ handoffkit report runs/latest
146
+ ```
147
+
148
+ `benchmark-doctor` uses 30 real cases from the public MedCaseReasoning test
149
+ split, derived from PMC Open Access case reports. It runs in `gold_replay` mode:
150
+ it replays clinician-authored diagnoses and reasoning to test HandoffKit
151
+ contracts, reports, quality scoring, and traceability. It does not claim model
152
+ diagnostic accuracy and is not medical advice.
153
+
154
+ MAI/SDBench-style public benchmark preview:
155
+
156
+ ```bash
157
+ handoffkit benchmark-doctor-mai --cases 30
158
+ handoffkit report runs/latest
159
+ ```
160
+
161
+ `benchmark-doctor-mai` mirrors the public mechanics described for SDBench:
162
+ opening note, gatekeeper, targeted questions, tests, simulated costs, final
163
+ diagnosis, trace, and replay. It uses public MedCaseReasoning / PMC Open Access
164
+ cases, not private NEJM SDBench data.
165
+
128
166
  ## Report Gallery
129
167
 
130
168
  Reports generated by the 1.2.0 demos:
@@ -134,6 +172,9 @@ Reports generated by the 1.2.0 demos:
134
172
  | Coding agents | [`reports/coding_review.md`](reports/coding_review.md) | `handoffkit showcase coding-review` |
135
173
  | Support escalation | [`reports/support_escalation.md`](reports/support_escalation.md) | `handoffkit showcase support-escalation` |
136
174
  | Research workflow | [`reports/research_workflow.md`](reports/research_workflow.md) | `handoffkit showcase research-workflow` |
175
+ | Doctor orchestrator | [`reports/doctor_orchestrator.md`](reports/doctor_orchestrator.md) | `handoffkit showcase doctor-orchestrator` |
176
+ | Doctor benchmark 30 | [`reports/doctor_benchmark_30.md`](reports/doctor_benchmark_30.md) | `handoffkit benchmark-doctor --cases 30` |
177
+ | MAI-style doctor benchmark 30 | [`reports/mai_style_doctor_benchmark_30.md`](reports/mai_style_doctor_benchmark_30.md) | `handoffkit benchmark-doctor-mai --cases 30` |
137
178
 
138
179
  Technical post: [`Context Soup vs Contract Handoffs`](docs/CONTEXT_SOUP_VS_CONTRACT_HANDOFFS.md).
139
180
  Launch copy for Hacker News, Reddit, X/LinkedIn, and LangGraph communities:
@@ -160,10 +201,81 @@ HandoffKit 1.2.0 improves the public demo experience:
160
201
  - `handoffkit showcase <slug>` runs a showcase and writes `runs/latest`,
161
202
  - `handoffkit init coding-review` now prints the next commands to run,
162
203
  - report gallery docs and SVG assets make README/PyPI easier to inspect,
204
+ - real-case doctor benchmark harness with 30 MedCaseReasoning / PMC Open Access cases,
205
+ - MAI/SDBench-style public sequential doctor benchmark with gatekeeper, costs,
206
+ trace, and replay,
163
207
  - Pydantic AI now has a runnable offline integration example,
164
208
  - integration docs include copy/paste adapter blocks for LangGraph, OpenAI
165
209
  Agents SDK, and Pydantic AI.
166
210
 
211
+ ## What 1.3.0 Adds
212
+
213
+ HandoffKit 1.3.0 is focused on stronger tool creation and
214
+ evidence-aware agent workflows:
215
+
216
+ - `ToolSpec`, `ToolFactory`, `DeclarativeTool`, and `HttpJsonTool` for building
217
+ provider-ready tools without hand-writing wrappers,
218
+ - public medical evidence lookup tools for PubMed, ClinicalTrials.gov, and
219
+ DailyMed,
220
+ - clinical MAI-style MiMo benchmark runner with multi-stage handoffs,
221
+ adversarial challenge, label normalization, and replayable reports.
222
+
223
+ Medical tools are for research and benchmark workflows only. They do not
224
+ diagnose, treat, or replace clinical judgment.
225
+
226
+ ```python
227
+ from handoffkit.tools import pubmed_search, clinical_trials_search, dailymed_drug_search
228
+
229
+ pubmed_search.run(query="scleroderma renal crisis case report", max_results=3)
230
+ clinical_trials_search.run(condition="systemic sclerosis", max_results=3)
231
+ dailymed_drug_search.run(drug_name="ibuprofen", max_results=3)
232
+ ```
233
+
234
+ ## What 1.4.0 Adds
235
+
236
+ HandoffKit 1.4.0 adds experimental provider routing:
237
+
238
+ - provider registry entries for OpenCode Go, OpenCode Zen, OpenAI-compatible
239
+ endpoints, and Ollama,
240
+ - `ProviderSelector` for offline model lists and real opt-in probes,
241
+ - `ProviderRouter` for ordered fallback between model candidates,
242
+ - retry/backoff for transient OpenCode `429`, `5xx`, and transport failures,
243
+ - `handoffkit providers ...` CLI commands that never call real APIs unless
244
+ `--real` is passed.
245
+
246
+ ```bash
247
+ handoffkit providers list
248
+ handoffkit providers models --provider opencode-go
249
+ handoffkit providers select --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --json
250
+ ```
251
+
252
+ Real probes require an explicit flag and a scoped provider key:
253
+
254
+ ```powershell
255
+ $env:OPENCODE_API_KEY="..."
256
+ handoffkit providers probe --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --real
257
+ ```
258
+
259
+ ## Provider Registry and Model Routing
260
+
261
+ The provider registry is experimental in 1.4.0. It is intended for diagnostics,
262
+ model selection, and fallback without adding heavy provider SDKs.
263
+
264
+ ```python
265
+ from handoffkit.providers import ModelCandidate, ProviderRouter
266
+
267
+ router = ProviderRouter(
268
+ [
269
+ ModelCandidate("opencode-go", "mimo-v2.5"),
270
+ ModelCandidate("opencode-go", "deepseek-v4-flash"),
271
+ ]
272
+ )
273
+
274
+ print(router.generate("Create a concise release checklist."))
275
+ ```
276
+
277
+ Docs: [`docs/PROVIDERS.md`](docs/PROVIDERS.md).
278
+
167
279
  ## What 1.1.0 Adds
168
280
 
169
281
  HandoffKit 1.1.0 focuses on adoption:
@@ -171,8 +283,11 @@ HandoffKit 1.1.0 focuses on adoption:
171
283
  - coding agents demo: `Architect -> Coder -> Reviewer -> Tester`,
172
284
  - customer support demo: `Triage -> Billing -> Refund -> Supervisor`,
173
285
  - research demo: `Researcher -> Extractor -> Fact-checker -> Writer`,
286
+ - educational doctor-orchestrator demo: `Intake -> Hypothesis -> Challenger ->
287
+ Test Steward -> Checklist -> Final Reviewer`,
174
288
  - direct templates through `handoffkit init coding-review`,
175
- `handoffkit init support-escalation`, and `handoffkit init research-workflow`,
289
+ `handoffkit init support-escalation`, `handoffkit init research-workflow`,
290
+ and `handoffkit init doctor-orchestrator`,
176
291
  - `handoffkit report runs/latest` for rendering generated run reports,
177
292
  - deterministic showcase reports that work offline and require no API key.
178
293
 
@@ -183,7 +298,11 @@ Use it as the contract and reporting layer beside orchestration frameworks:
183
298
 
184
299
  - [`LangGraph`](docs/integrations/LANGGRAPH.md): graph nodes pass `HandoffState`,
185
300
  - [`OpenAI Agents SDK`](docs/integrations/OPENAI_AGENTS.md): agent handoffs become auditable contracts,
186
- - [`Pydantic AI`](docs/integrations/PYDANTIC_AI.md): typed outputs become workflow handoff state.
301
+ - [`Pydantic AI`](docs/integrations/PYDANTIC_AI.md): typed outputs become workflow handoff state,
302
+ - [`OpenCode Go / Zen`](docs/integrations/OPENCODE.md): provider adapters route
303
+ OpenCode model families to their matching API endpoint styles.
304
+ - [`Provider Registry`](docs/PROVIDERS.md): experimental provider listing,
305
+ probing, model selection, and fallback routing.
187
306
 
188
307
  Runnable offline examples:
189
308
  [`examples/langgraph_integration.py`](examples/langgraph_integration.py),
@@ -328,6 +447,9 @@ HandoffKit gives you:
328
447
  - `EchoProvider`: deterministic local provider for tests and demos.
329
448
  - `OllamaProvider`: local Ollama integration.
330
449
  - `OpenAIProvider`: OpenAI and OpenAI-compatible APIs.
450
+ - `OpenCodeZenProvider`: OpenCode Zen with GPT, Claude, Qwen, DeepSeek,
451
+ MiniMax, GLM, Kimi, MiMo, Grok, and free model routing.
452
+ - `OpenCodeGoProvider`: OpenCode Go with curated open coding models.
331
453
 
332
454
  ## Core Concept
333
455
 
@@ -727,6 +849,7 @@ handoffkit demo-replay
727
849
  handoffkit demo-coding-review
728
850
  handoffkit demo-support
729
851
  handoffkit demo-research
852
+ handoffkit demo-doctor
730
853
  handoffkit report runs/latest
731
854
  handoffkit validate-report reports/trace_demo.json
732
855
  handoffkit evaluate reports/trace_demo.json
@@ -954,6 +1077,42 @@ pytest tests_api -q
954
1077
 
955
1078
  Use temporary or scoped provider tokens. Do not commit API keys.
956
1079
 
1080
+ ### OpenCode Go and OpenCode Zen
1081
+
1082
+ HandoffKit can call OpenCode Go and OpenCode Zen without adding provider SDK
1083
+ dependencies. Use one `OPENCODE_API_KEY`; choose the catalog-specific model with
1084
+ `OPENCODE_GO_MODEL` or `OPENCODE_ZEN_MODEL`.
1085
+
1086
+ ```powershell
1087
+ $env:OPENCODE_API_KEY="..."
1088
+ $env:OPENCODE_GO_MODEL="deepseek-v4-flash"
1089
+ python examples/opencode_go_agent.py
1090
+ ```
1091
+
1092
+ ```powershell
1093
+ $env:OPENCODE_API_KEY="..."
1094
+ $env:OPENCODE_ZEN_MODEL="gpt-5.4"
1095
+ python examples/opencode_zen_agent.py
1096
+ ```
1097
+
1098
+ Supported routing:
1099
+
1100
+ | Provider | Model family | Endpoint style |
1101
+ |---|---|---|
1102
+ | OpenCode Go | GLM, Kimi, MiMo, DeepSeek | `/chat/completions` |
1103
+ | OpenCode Go | MiniMax, Qwen | `/messages` |
1104
+ | OpenCode Zen | GPT | `/responses` |
1105
+ | OpenCode Zen | Claude, Qwen | `/messages` |
1106
+ | OpenCode Zen | DeepSeek, MiniMax, GLM, Kimi, Grok, free models | `/chat/completions` |
1107
+
1108
+ Model ids may use OpenCode config prefixes such as `opencode-go/kimi-k2.7-code`
1109
+ or `opencode/gpt-5.4`; HandoffKit strips those prefixes before sending requests.
1110
+ Gemini models use OpenCode's Google-style endpoint and currently fail with a
1111
+ clear configuration error.
1112
+
1113
+ Docs:
1114
+ [`docs/integrations/OPENCODE.md`](docs/integrations/OPENCODE.md).
1115
+
957
1116
  ## CLI
958
1117
 
959
1118
  ```bash
@@ -973,6 +1132,9 @@ handoffkit demo-trace
973
1132
  handoffkit demo-replay
974
1133
  handoffkit validate-report reports/trace_demo.json
975
1134
  handoffkit evaluate reports/trace_demo.json
1135
+ handoffkit providers list
1136
+ handoffkit providers models --provider opencode-go
1137
+ handoffkit providers select --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --json
976
1138
  handoffkit init my-agent --template basic-agent --output .
977
1139
  ```
978
1140
 
@@ -983,11 +1145,14 @@ python examples/simple_agent.py
983
1145
  python examples/coding_review.py
984
1146
  python examples/support_escalation.py
985
1147
  python examples/research_workflow.py
1148
+ python examples/doctor_orchestrator.py
986
1149
  python examples/handoff_demo.py
987
1150
  python examples/coding_team.py
988
1151
  python examples/tool_schema_demo.py
989
1152
  python examples/tool_execution_demo.py
990
1153
  python examples/fake_provider_tool_call_demo.py
1154
+ python examples/opencode_go_agent.py
1155
+ python examples/opencode_zen_agent.py
991
1156
  python examples/structured_output_demo.py
992
1157
  python examples/provider_tool_adapter_demo.py
993
1158
  python examples/handoff_quality_demo.py
@@ -1074,3 +1239,4 @@ HandoffKit is a developer library, not a copy of that repository.
1074
1239
  ## License
1075
1240
 
1076
1241
  MIT.
1242
+
@@ -1,4 +1,4 @@
1
- <div align="center">
1
+ <div align="center">
2
2
 
3
3
  <img src="https://raw.githubusercontent.com/DaosPath/handoffkit/main/docs/assets/handoffkit-hero.svg" alt="HandoffKit: structured state transfer for multi-agent Python workflows" width="100%">
4
4
 
@@ -93,6 +93,44 @@ replay evidence stay attached to the work.
93
93
 
94
94
  <img src="https://raw.githubusercontent.com/DaosPath/handoffkit/main/docs/assets/handoffkit-report-gallery.svg" alt="HandoffKit report gallery for coding agents, support escalation, and research workflow" width="100%">
95
95
 
96
+ Bonus educational healthcare workflow:
97
+
98
+ ```bash
99
+ handoffkit showcase doctor-orchestrator
100
+ handoffkit report runs/latest
101
+ ```
102
+
103
+ `doctor-orchestrator` is a synthetic demo inspired by virtual physician-panel
104
+ orchestration patterns: Intake -> Hypothesis -> Challenger -> Test Steward ->
105
+ Checklist -> Final Reviewer. It demonstrates structured uncertainty, missing
106
+ questions, red-flag tracking, cost-aware test reasoning, and replayable review
107
+ evidence. It is not medical advice.
108
+
109
+ Real open-access case benchmark preview:
110
+
111
+ ```bash
112
+ handoffkit benchmark-doctor --cases 30
113
+ handoffkit report runs/latest
114
+ ```
115
+
116
+ `benchmark-doctor` uses 30 real cases from the public MedCaseReasoning test
117
+ split, derived from PMC Open Access case reports. It runs in `gold_replay` mode:
118
+ it replays clinician-authored diagnoses and reasoning to test HandoffKit
119
+ contracts, reports, quality scoring, and traceability. It does not claim model
120
+ diagnostic accuracy and is not medical advice.
121
+
122
+ MAI/SDBench-style public benchmark preview:
123
+
124
+ ```bash
125
+ handoffkit benchmark-doctor-mai --cases 30
126
+ handoffkit report runs/latest
127
+ ```
128
+
129
+ `benchmark-doctor-mai` mirrors the public mechanics described for SDBench:
130
+ opening note, gatekeeper, targeted questions, tests, simulated costs, final
131
+ diagnosis, trace, and replay. It uses public MedCaseReasoning / PMC Open Access
132
+ cases, not private NEJM SDBench data.
133
+
96
134
  ## Report Gallery
97
135
 
98
136
  Reports generated by the 1.2.0 demos:
@@ -102,6 +140,9 @@ Reports generated by the 1.2.0 demos:
102
140
  | Coding agents | [`reports/coding_review.md`](reports/coding_review.md) | `handoffkit showcase coding-review` |
103
141
  | Support escalation | [`reports/support_escalation.md`](reports/support_escalation.md) | `handoffkit showcase support-escalation` |
104
142
  | Research workflow | [`reports/research_workflow.md`](reports/research_workflow.md) | `handoffkit showcase research-workflow` |
143
+ | Doctor orchestrator | [`reports/doctor_orchestrator.md`](reports/doctor_orchestrator.md) | `handoffkit showcase doctor-orchestrator` |
144
+ | Doctor benchmark 30 | [`reports/doctor_benchmark_30.md`](reports/doctor_benchmark_30.md) | `handoffkit benchmark-doctor --cases 30` |
145
+ | MAI-style doctor benchmark 30 | [`reports/mai_style_doctor_benchmark_30.md`](reports/mai_style_doctor_benchmark_30.md) | `handoffkit benchmark-doctor-mai --cases 30` |
105
146
 
106
147
  Technical post: [`Context Soup vs Contract Handoffs`](docs/CONTEXT_SOUP_VS_CONTRACT_HANDOFFS.md).
107
148
  Launch copy for Hacker News, Reddit, X/LinkedIn, and LangGraph communities:
@@ -128,10 +169,81 @@ HandoffKit 1.2.0 improves the public demo experience:
128
169
  - `handoffkit showcase <slug>` runs a showcase and writes `runs/latest`,
129
170
  - `handoffkit init coding-review` now prints the next commands to run,
130
171
  - report gallery docs and SVG assets make README/PyPI easier to inspect,
172
+ - real-case doctor benchmark harness with 30 MedCaseReasoning / PMC Open Access cases,
173
+ - MAI/SDBench-style public sequential doctor benchmark with gatekeeper, costs,
174
+ trace, and replay,
131
175
  - Pydantic AI now has a runnable offline integration example,
132
176
  - integration docs include copy/paste adapter blocks for LangGraph, OpenAI
133
177
  Agents SDK, and Pydantic AI.
134
178
 
179
+ ## What 1.3.0 Adds
180
+
181
+ HandoffKit 1.3.0 is focused on stronger tool creation and
182
+ evidence-aware agent workflows:
183
+
184
+ - `ToolSpec`, `ToolFactory`, `DeclarativeTool`, and `HttpJsonTool` for building
185
+ provider-ready tools without hand-writing wrappers,
186
+ - public medical evidence lookup tools for PubMed, ClinicalTrials.gov, and
187
+ DailyMed,
188
+ - clinical MAI-style MiMo benchmark runner with multi-stage handoffs,
189
+ adversarial challenge, label normalization, and replayable reports.
190
+
191
+ Medical tools are for research and benchmark workflows only. They do not
192
+ diagnose, treat, or replace clinical judgment.
193
+
194
+ ```python
195
+ from handoffkit.tools import pubmed_search, clinical_trials_search, dailymed_drug_search
196
+
197
+ pubmed_search.run(query="scleroderma renal crisis case report", max_results=3)
198
+ clinical_trials_search.run(condition="systemic sclerosis", max_results=3)
199
+ dailymed_drug_search.run(drug_name="ibuprofen", max_results=3)
200
+ ```
201
+
202
+ ## What 1.4.0 Adds
203
+
204
+ HandoffKit 1.4.0 adds experimental provider routing:
205
+
206
+ - provider registry entries for OpenCode Go, OpenCode Zen, OpenAI-compatible
207
+ endpoints, and Ollama,
208
+ - `ProviderSelector` for offline model lists and real opt-in probes,
209
+ - `ProviderRouter` for ordered fallback between model candidates,
210
+ - retry/backoff for transient OpenCode `429`, `5xx`, and transport failures,
211
+ - `handoffkit providers ...` CLI commands that never call real APIs unless
212
+ `--real` is passed.
213
+
214
+ ```bash
215
+ handoffkit providers list
216
+ handoffkit providers models --provider opencode-go
217
+ handoffkit providers select --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --json
218
+ ```
219
+
220
+ Real probes require an explicit flag and a scoped provider key:
221
+
222
+ ```powershell
223
+ $env:OPENCODE_API_KEY="..."
224
+ handoffkit providers probe --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --real
225
+ ```
226
+
227
+ ## Provider Registry and Model Routing
228
+
229
+ The provider registry is experimental in 1.4.0. It is intended for diagnostics,
230
+ model selection, and fallback without adding heavy provider SDKs.
231
+
232
+ ```python
233
+ from handoffkit.providers import ModelCandidate, ProviderRouter
234
+
235
+ router = ProviderRouter(
236
+ [
237
+ ModelCandidate("opencode-go", "mimo-v2.5"),
238
+ ModelCandidate("opencode-go", "deepseek-v4-flash"),
239
+ ]
240
+ )
241
+
242
+ print(router.generate("Create a concise release checklist."))
243
+ ```
244
+
245
+ Docs: [`docs/PROVIDERS.md`](docs/PROVIDERS.md).
246
+
135
247
  ## What 1.1.0 Adds
136
248
 
137
249
  HandoffKit 1.1.0 focuses on adoption:
@@ -139,8 +251,11 @@ HandoffKit 1.1.0 focuses on adoption:
139
251
  - coding agents demo: `Architect -> Coder -> Reviewer -> Tester`,
140
252
  - customer support demo: `Triage -> Billing -> Refund -> Supervisor`,
141
253
  - research demo: `Researcher -> Extractor -> Fact-checker -> Writer`,
254
+ - educational doctor-orchestrator demo: `Intake -> Hypothesis -> Challenger ->
255
+ Test Steward -> Checklist -> Final Reviewer`,
142
256
  - direct templates through `handoffkit init coding-review`,
143
- `handoffkit init support-escalation`, and `handoffkit init research-workflow`,
257
+ `handoffkit init support-escalation`, `handoffkit init research-workflow`,
258
+ and `handoffkit init doctor-orchestrator`,
144
259
  - `handoffkit report runs/latest` for rendering generated run reports,
145
260
  - deterministic showcase reports that work offline and require no API key.
146
261
 
@@ -151,7 +266,11 @@ Use it as the contract and reporting layer beside orchestration frameworks:
151
266
 
152
267
  - [`LangGraph`](docs/integrations/LANGGRAPH.md): graph nodes pass `HandoffState`,
153
268
  - [`OpenAI Agents SDK`](docs/integrations/OPENAI_AGENTS.md): agent handoffs become auditable contracts,
154
- - [`Pydantic AI`](docs/integrations/PYDANTIC_AI.md): typed outputs become workflow handoff state.
269
+ - [`Pydantic AI`](docs/integrations/PYDANTIC_AI.md): typed outputs become workflow handoff state,
270
+ - [`OpenCode Go / Zen`](docs/integrations/OPENCODE.md): provider adapters route
271
+ OpenCode model families to their matching API endpoint styles.
272
+ - [`Provider Registry`](docs/PROVIDERS.md): experimental provider listing,
273
+ probing, model selection, and fallback routing.
155
274
 
156
275
  Runnable offline examples:
157
276
  [`examples/langgraph_integration.py`](examples/langgraph_integration.py),
@@ -296,6 +415,9 @@ HandoffKit gives you:
296
415
  - `EchoProvider`: deterministic local provider for tests and demos.
297
416
  - `OllamaProvider`: local Ollama integration.
298
417
  - `OpenAIProvider`: OpenAI and OpenAI-compatible APIs.
418
+ - `OpenCodeZenProvider`: OpenCode Zen with GPT, Claude, Qwen, DeepSeek,
419
+ MiniMax, GLM, Kimi, MiMo, Grok, and free model routing.
420
+ - `OpenCodeGoProvider`: OpenCode Go with curated open coding models.
299
421
 
300
422
  ## Core Concept
301
423
 
@@ -695,6 +817,7 @@ handoffkit demo-replay
695
817
  handoffkit demo-coding-review
696
818
  handoffkit demo-support
697
819
  handoffkit demo-research
820
+ handoffkit demo-doctor
698
821
  handoffkit report runs/latest
699
822
  handoffkit validate-report reports/trace_demo.json
700
823
  handoffkit evaluate reports/trace_demo.json
@@ -922,6 +1045,42 @@ pytest tests_api -q
922
1045
 
923
1046
  Use temporary or scoped provider tokens. Do not commit API keys.
924
1047
 
1048
+ ### OpenCode Go and OpenCode Zen
1049
+
1050
+ HandoffKit can call OpenCode Go and OpenCode Zen without adding provider SDK
1051
+ dependencies. Use one `OPENCODE_API_KEY`; choose the catalog-specific model with
1052
+ `OPENCODE_GO_MODEL` or `OPENCODE_ZEN_MODEL`.
1053
+
1054
+ ```powershell
1055
+ $env:OPENCODE_API_KEY="..."
1056
+ $env:OPENCODE_GO_MODEL="deepseek-v4-flash"
1057
+ python examples/opencode_go_agent.py
1058
+ ```
1059
+
1060
+ ```powershell
1061
+ $env:OPENCODE_API_KEY="..."
1062
+ $env:OPENCODE_ZEN_MODEL="gpt-5.4"
1063
+ python examples/opencode_zen_agent.py
1064
+ ```
1065
+
1066
+ Supported routing:
1067
+
1068
+ | Provider | Model family | Endpoint style |
1069
+ |---|---|---|
1070
+ | OpenCode Go | GLM, Kimi, MiMo, DeepSeek | `/chat/completions` |
1071
+ | OpenCode Go | MiniMax, Qwen | `/messages` |
1072
+ | OpenCode Zen | GPT | `/responses` |
1073
+ | OpenCode Zen | Claude, Qwen | `/messages` |
1074
+ | OpenCode Zen | DeepSeek, MiniMax, GLM, Kimi, Grok, free models | `/chat/completions` |
1075
+
1076
+ Model ids may use OpenCode config prefixes such as `opencode-go/kimi-k2.7-code`
1077
+ or `opencode/gpt-5.4`; HandoffKit strips those prefixes before sending requests.
1078
+ Gemini models use OpenCode's Google-style endpoint and currently fail with a
1079
+ clear configuration error.
1080
+
1081
+ Docs:
1082
+ [`docs/integrations/OPENCODE.md`](docs/integrations/OPENCODE.md).
1083
+
925
1084
  ## CLI
926
1085
 
927
1086
  ```bash
@@ -941,6 +1100,9 @@ handoffkit demo-trace
941
1100
  handoffkit demo-replay
942
1101
  handoffkit validate-report reports/trace_demo.json
943
1102
  handoffkit evaluate reports/trace_demo.json
1103
+ handoffkit providers list
1104
+ handoffkit providers models --provider opencode-go
1105
+ handoffkit providers select --provider opencode-go --models mimo-v2.5,deepseek-v4-flash --json
944
1106
  handoffkit init my-agent --template basic-agent --output .
945
1107
  ```
946
1108
 
@@ -951,11 +1113,14 @@ python examples/simple_agent.py
951
1113
  python examples/coding_review.py
952
1114
  python examples/support_escalation.py
953
1115
  python examples/research_workflow.py
1116
+ python examples/doctor_orchestrator.py
954
1117
  python examples/handoff_demo.py
955
1118
  python examples/coding_team.py
956
1119
  python examples/tool_schema_demo.py
957
1120
  python examples/tool_execution_demo.py
958
1121
  python examples/fake_provider_tool_call_demo.py
1122
+ python examples/opencode_go_agent.py
1123
+ python examples/opencode_zen_agent.py
959
1124
  python examples/structured_output_demo.py
960
1125
  python examples/provider_tool_adapter_demo.py
961
1126
  python examples/handoff_quality_demo.py
@@ -1042,3 +1207,4 @@ HandoffKit is a developer library, not a copy of that repository.
1042
1207
  ## License
1043
1208
 
1044
1209
  MIT.
1210
+
@@ -0,0 +1,7 @@
1
+ """Run the real-case offline doctor benchmark harness."""
2
+
3
+ from handoffkit.doctor_benchmark import run_doctor_benchmark
4
+
5
+ if __name__ == "__main__":
6
+ result = run_doctor_benchmark(30)
7
+ print(result.to_markdown())
@@ -0,0 +1,13 @@
1
+ """Educational diagnostic-orchestrator showcase.
2
+
3
+ This is a synthetic workflow demo. It is not medical advice and does not produce
4
+ patient-specific diagnosis or treatment.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from handoffkit import run_showcase
10
+
11
+ if __name__ == "__main__":
12
+ result = run_showcase("doctor-orchestrator")
13
+ print(result.to_markdown())