agentbyte 0.42.3__tar.gz → 0.43.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 (372) hide show
  1. {agentbyte-0.42.3 → agentbyte-0.43.0}/CHANGELOG.md +31 -0
  2. {agentbyte-0.42.3 → agentbyte-0.43.0}/PKG-INFO +2 -2
  3. {agentbyte-0.42.3 → agentbyte-0.43.0}/README.md +1 -1
  4. agentbyte-0.43.0/src/agentbyte/__about__.py +2 -0
  5. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/agent.py +16 -1
  6. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/base.py +18 -0
  7. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/ai.py +4 -0
  8. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/base.py +50 -0
  9. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/handoff.py +6 -0
  10. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/plan.py +4 -0
  11. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/policies.py +5 -1
  12. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/round_robin.py +4 -0
  13. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/agent.py +1 -0
  14. agentbyte-0.43.0/tests/agents/test_agent_stop_at_tools.py +170 -0
  15. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestrator_agent_contract.py +44 -12
  16. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestrator_synthesis.py +90 -1
  17. agentbyte-0.42.3/src/agentbyte/__about__.py +0 -2
  18. {agentbyte-0.42.3 → agentbyte-0.43.0}/.gitignore +0 -0
  19. {agentbyte-0.42.3 → agentbyte-0.43.0}/LICENSE +0 -0
  20. {agentbyte-0.42.3 → agentbyte-0.43.0}/pyproject.toml +0 -0
  21. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/__init__.py +0 -0
  22. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/_optional.py +0 -0
  23. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/__init__.py +0 -0
  24. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/agent_as_tool.py +0 -0
  25. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/embedding_agent.py +0 -0
  26. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/agents/types.py +0 -0
  27. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cancellation_token.py +0 -0
  28. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/catalog.py +0 -0
  29. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cli/__init__.py +0 -0
  30. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cli/__main__.py +0 -0
  31. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cli/eval_commands.py +0 -0
  32. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cli/loading.py +0 -0
  33. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/cli/main.py +0 -0
  34. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/compaction/__init__.py +0 -0
  35. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/compaction/counters.py +0 -0
  36. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/compaction/errors.py +0 -0
  37. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/compaction/grouping.py +0 -0
  38. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/compaction/strategies.py +0 -0
  39. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/component.py +0 -0
  40. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/context.py +0 -0
  41. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/context_providers/__init__.py +0 -0
  42. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/context_providers/base.py +0 -0
  43. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/context_providers/skill_tools.py +0 -0
  44. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/context_providers/skills.py +0 -0
  45. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/__init__.py +0 -0
  46. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/_aiosqlite.py +0 -0
  47. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/base.py +0 -0
  48. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/config.py +0 -0
  49. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/importer.py +0 -0
  50. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/json.py +0 -0
  51. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/loader.py +0 -0
  52. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/publish.py +0 -0
  53. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/publish_config.py +0 -0
  54. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/publishers.py +0 -0
  55. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/s3.py +0 -0
  56. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/sources.py +0 -0
  57. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/sqlite.py +0 -0
  58. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/sqlite_db.py +0 -0
  59. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/write_config.py +0 -0
  60. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/dataset/writers.py +0 -0
  61. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/entity.py +0 -0
  62. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/__init__.py +0 -0
  63. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/base.py +0 -0
  64. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/__init__.py +0 -0
  65. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/decorator.py +0 -0
  66. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/keyword.py +0 -0
  67. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/local.py +0 -0
  68. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/process.py +0 -0
  69. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/tool.py +0 -0
  70. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/checks/types.py +0 -0
  71. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/comparison.py +0 -0
  72. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/eval_dataset.py +0 -0
  73. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/__init__.py +0 -0
  74. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/conformance.py +0 -0
  75. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/errors.py +0 -0
  76. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/models.py +0 -0
  77. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/recorder.py +0 -0
  78. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/sql.py +0 -0
  79. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/sqlite.py +0 -0
  80. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/store.py +0 -0
  81. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/history/transitions.py +0 -0
  82. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/__init__.py +0 -0
  83. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/base.py +0 -0
  84. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/composite.py +0 -0
  85. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/llm.py +0 -0
  86. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/pairwise.py +0 -0
  87. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/reference.py +0 -0
  88. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/trajectory.py +0 -0
  89. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/judges/validation.py +0 -0
  90. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/pairwise.py +0 -0
  91. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/report.py +0 -0
  92. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/runner.py +0 -0
  93. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/splitting.py +0 -0
  94. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/__init__.py +0 -0
  95. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/agent.py +0 -0
  96. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/model.py +0 -0
  97. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/multi_turn.py +0 -0
  98. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/orchestrator.py +0 -0
  99. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/runtime.py +0 -0
  100. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/targets/workflow.py +0 -0
  101. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/types.py +0 -0
  102. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/__init__.py +0 -0
  103. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/coordinator.py +0 -0
  104. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/jobs.py +0 -0
  105. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/smoke.py +0 -0
  106. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/smoke_tasks.json +0 -0
  107. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/suite.py +0 -0
  108. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/eval/workbench/verdict.py +0 -0
  109. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/execution_trace/__init__.py +0 -0
  110. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/execution_trace/collector.py +0 -0
  111. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/execution_trace/models.py +0 -0
  112. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/__init__.py +0 -0
  113. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/_retry_observability.py +0 -0
  114. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/auth.py +0 -0
  115. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure/__init__.py +0 -0
  116. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure/auth.py +0 -0
  117. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure/chat.py +0 -0
  118. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure/embedding.py +0 -0
  119. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure/settings.py +0 -0
  120. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure_openai.py +0 -0
  121. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/azure_openai_embedding.py +0 -0
  122. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/base.py +0 -0
  123. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/embeddings_base.py +0 -0
  124. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/openai/__init__.py +0 -0
  125. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/openai/chat.py +0 -0
  126. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/openai/embedding.py +0 -0
  127. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/openai/settings.py +0 -0
  128. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/openai_embedding.py +0 -0
  129. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/pricing.py +0 -0
  130. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/retry_policy.py +0 -0
  131. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/settings.py +0 -0
  132. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/llm/types.py +0 -0
  133. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/logger.py +0 -0
  134. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/memory/__init__.py +0 -0
  135. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/memory/base.py +0 -0
  136. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/messages.py +0 -0
  137. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/__init__.py +0 -0
  138. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/base.py +0 -0
  139. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/otel.py +0 -0
  140. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/retry.py +0 -0
  141. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/sql_usage.py +0 -0
  142. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/middleware/usage_logger.py +0 -0
  143. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/notebook.py +0 -0
  144. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/__init__.py +0 -0
  145. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/base.py +0 -0
  146. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/config.py +0 -0
  147. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/gepa.py +0 -0
  148. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/mipro.py +0 -0
  149. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/pareto.py +0 -0
  150. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/reflective.py +0 -0
  151. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/spec.py +0 -0
  152. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/optim/trace.py +0 -0
  153. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/orchestration/__init__.py +0 -0
  154. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/__init__.py +0 -0
  155. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/agents.py +0 -0
  156. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/clients.py +0 -0
  157. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instruction_registry.py +0 -0
  158. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instructions/orchestrator.yaml +0 -0
  159. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instructions/query_rewriter.yaml +0 -0
  160. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instructions/researcher.yaml +0 -0
  161. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instructions/reviewer.yaml +0 -0
  162. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/instructions/writer.yaml +0 -0
  163. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/orchestration.py +0 -0
  164. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/skills/contracts-analyst/SKILL.md +0 -0
  165. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/skills/hr-analyst/SKILL.md +0 -0
  166. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/skills/hr-analyst/resources/departments.md +0 -0
  167. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/skills/hr-analyst/resources/employees.md +0 -0
  168. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/skills/hr-analyst/resources/payroll.md +0 -0
  169. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/streaming.py +0 -0
  170. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/presets/workflow.py +0 -0
  171. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/session_store.py +0 -0
  172. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/__init__.py +0 -0
  173. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/base.py +0 -0
  174. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/resources.py +0 -0
  175. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/scripts.py +0 -0
  176. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/sources.py +0 -0
  177. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/skills/validation.py +0 -0
  178. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/__init__.py +0 -0
  179. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/base.py +0 -0
  180. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/cancellation.py +0 -0
  181. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/composite.py +0 -0
  182. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/consecutive_agent.py +0 -0
  183. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/external.py +0 -0
  184. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/function_call.py +0 -0
  185. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/handoff.py +0 -0
  186. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/max_message.py +0 -0
  187. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/predicate.py +0 -0
  188. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/source.py +0 -0
  189. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/text_mention.py +0 -0
  190. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/timeout.py +0 -0
  191. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/termination/token_usage.py +0 -0
  192. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/__init__.py +0 -0
  193. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/base.py +0 -0
  194. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/coding_tools.py +0 -0
  195. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/core_tools.py +0 -0
  196. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/decorator.py +0 -0
  197. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/memory_tool.py +0 -0
  198. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/tools/research_tools.py +0 -0
  199. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/types.py +0 -0
  200. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/__init__.py +0 -0
  201. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/discovery.py +0 -0
  202. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/eval_routes.py +0 -0
  203. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/execution.py +0 -0
  204. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/models.py +0 -0
  205. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/registry.py +0 -0
  206. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/server.py +0 -0
  207. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/session_store.py +0 -0
  208. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/sessions.py +0 -0
  209. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/ui/assets/index-BsS4WYZu.css +0 -0
  210. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/ui/assets/index-tGvO1yue.js +0 -0
  211. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/ui/index.html +0 -0
  212. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/webui/ui/vite.svg +0 -0
  213. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/__init__.py +0 -0
  214. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/__init__.py +0 -0
  215. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/_structure_hash.py +0 -0
  216. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/checkpoint.py +0 -0
  217. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/models.py +0 -0
  218. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/runner.py +0 -0
  219. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/core/workflow.py +0 -0
  220. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/defaults.py +0 -0
  221. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/errors.py +0 -0
  222. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/loader.py +0 -0
  223. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/schema.py +0 -0
  224. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/schema_utils.py +0 -0
  225. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/sqlite_checkpoint.py +0 -0
  226. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/__init__.py +0 -0
  227. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/agent.py +0 -0
  228. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/echo.py +0 -0
  229. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/function.py +0 -0
  230. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/http.py +0 -0
  231. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/step.py +0 -0
  232. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/subworkflow.py +0 -0
  233. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/steps/transform.py +0 -0
  234. {agentbyte-0.42.3 → agentbyte-0.43.0}/src/agentbyte/workflow/visualizer.py +0 -0
  235. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_as_tool.py +0 -0
  236. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_basic.py +0 -0
  237. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_context_providers.py +0 -0
  238. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_error_response.py +0 -0
  239. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_event_types.py +0 -0
  240. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_memory_integration.py +0 -0
  241. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_middleware_integration.py +0 -0
  242. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_response_accessors.py +0 -0
  243. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_retry_middleware.py +0 -0
  244. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_agent_stream_events.py +0 -0
  245. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_embedding_agent.py +0 -0
  246. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_tool_approval.py +0 -0
  247. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_tool_batch_resolution.py +0 -0
  248. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/agents/test_tool_metadata.py +0 -0
  249. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/cli/test_loading.py +0 -0
  250. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/cli/test_registry_check.py +0 -0
  251. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/compaction/test_compaction.py +0 -0
  252. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/context_providers/__init__.py +0 -0
  253. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/context_providers/test_skill_tools.py +0 -0
  254. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/context_providers/test_skills_provider.py +0 -0
  255. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/fake_s3.py +0 -0
  256. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/test_dataset_exit.py +0 -0
  257. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/test_loader.py +0 -0
  258. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/test_multi_table.py +0 -0
  259. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/test_publish.py +0 -0
  260. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/dataset/test_sqlite_db.py +0 -0
  261. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_eval_dataset.py +0 -0
  262. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_eval_history.py +0 -0
  263. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_eval_history_backends.py +0 -0
  264. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_eval_jobs.py +0 -0
  265. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_eval_workbench.py +0 -0
  266. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_execution_trajectories.py +0 -0
  267. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_multi_turn.py +0 -0
  268. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_pairwise.py +0 -0
  269. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_phase1_runner_and_targets.py +0 -0
  270. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_phase2_checks_and_reports.py +0 -0
  271. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_score_integrity.py +0 -0
  272. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_splitting.py +0 -0
  273. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/eval/test_types_and_judges.py +0 -0
  274. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/examples/test_compaction_webapp.py +0 -0
  275. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_azure_client.py +0 -0
  276. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_azure_embedding_client.py +0 -0
  277. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_llm_types.py +0 -0
  278. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_openai_client.py +0 -0
  279. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_openai_embedding_client.py +0 -0
  280. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_pricing.py +0 -0
  281. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_retry_observability.py +0 -0
  282. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_retry_policy_api.py +0 -0
  283. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/llm/test_retryable_error_substrings.py +0 -0
  284. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/memory/test_memory.py +0 -0
  285. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_context_compaction.py +0 -0
  286. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_deduplicate_tool_result.py +0 -0
  287. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_middleware_chain.py +0 -0
  288. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_otel.py +0 -0
  289. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_retry_middleware.py +0 -0
  290. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_sql_usage.py +0 -0
  291. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/middleware/test_usage_logger.py +0 -0
  292. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/__init__.py +0 -0
  293. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_base.py +0 -0
  294. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_base_integration.py +0 -0
  295. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_config.py +0 -0
  296. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_description_tunable.py +0 -0
  297. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_gepa.py +0 -0
  298. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_mipro.py +0 -0
  299. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_orchestrator_optim.py +0 -0
  300. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_pareto.py +0 -0
  301. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_reflective.py +0 -0
  302. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_score_integrity.py +0 -0
  303. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_spec.py +0 -0
  304. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/optim/test_trace.py +0 -0
  305. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_ai_orchestrator.py +0 -0
  306. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_base_orchestrator.py +0 -0
  307. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_handoff_orchestrator.py +0 -0
  308. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_history_tool_call_pairing.py +0 -0
  309. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestration_usage_breakdown.py +0 -0
  310. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestrator_finalization.py +0 -0
  311. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestrator_member_events.py +0 -0
  312. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_orchestrator_otel.py +0 -0
  313. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_plan_orchestrator.py +0 -0
  314. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/orchestration/test_round_robin.py +0 -0
  315. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_agents.py +0 -0
  316. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_clients.py +0 -0
  317. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_instruction_registry.py +0 -0
  318. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_orchestration.py +0 -0
  319. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_streaming.py +0 -0
  320. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/presets/test_workflow.py +0 -0
  321. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/skills/__init__.py +0 -0
  322. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/skills/test_base.py +0 -0
  323. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/skills/test_resources.py +0 -0
  324. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/skills/test_scripts.py +0 -0
  325. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/skills/test_sources.py +0 -0
  326. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_base.py +0 -0
  327. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_cancellation.py +0 -0
  328. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_composite.py +0 -0
  329. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_consecutive_agent.py +0 -0
  330. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_external.py +0 -0
  331. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_function_call.py +0 -0
  332. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_handoff.py +0 -0
  333. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_max_message.py +0 -0
  334. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_predicate.py +0 -0
  335. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_source.py +0 -0
  336. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_text_mention.py +0 -0
  337. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_timeout.py +0 -0
  338. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/termination/test_token_usage.py +0 -0
  339. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_cancellation_token.py +0 -0
  340. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_context.py +0 -0
  341. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_logger.py +0 -0
  342. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_messages.py +0 -0
  343. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_optional_extras.py +0 -0
  344. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_package_api.py +0 -0
  345. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_session_store.py +0 -0
  346. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_types.py +0 -0
  347. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/test_vanilla_chunker.py +0 -0
  348. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/tools/test_coding_tools.py +0 -0
  349. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/tools/test_memory_tool.py +0 -0
  350. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/tools/test_research_tools.py +0 -0
  351. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/tools/test_tools.py +0 -0
  352. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/__init__.py +0 -0
  353. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/helpers.py +0 -0
  354. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_eval_routes.py +0 -0
  355. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_execution.py +0 -0
  356. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_package_api.py +0 -0
  357. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_registry.py +0 -0
  358. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_server.py +0 -0
  359. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_sessions.py +0 -0
  360. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/webui/test_workflow_streaming.py +0 -0
  361. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/recovery_worker.py +0 -0
  362. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_agent_step_imports.py +0 -0
  363. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_checkpoint.py +0 -0
  364. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_subworkflow_step.py +0 -0
  365. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_agent.py +0 -0
  366. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_class.py +0 -0
  367. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_models.py +0 -0
  368. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_reliability.py +0 -0
  369. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_runner.py +0 -0
  370. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_schema.py +0 -0
  371. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_steps.py +0 -0
  372. {agentbyte-0.42.3 → agentbyte-0.43.0}/tests/workflow/test_workflow_visualizer.py +0 -0
@@ -6,6 +6,37 @@ The format follows Keep a Changelog principles and semantic versioning.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.43.0] - 2026-10-05
10
+
11
+ ### Added
12
+
13
+ - Agents: `stop_at_tools=[...]` ends the run with `finish_reason="tool_executed"`, without a
14
+ final model call, once a call to a named tool succeeds. Multi-step tool discovery and retries
15
+ after a failed call still run; a failed stop tool does not stop the run; the budget-exhaustion
16
+ finalization still applies. Names are validated against the agent's tools at construction.
17
+ Meant for team specialists whose raw tool results a synthesizer turns into the answer.
18
+ - Orchestration: `AgentHistoryPolicy(window="run")` sends this run's messages in full and
19
+ condenses earlier session turns to each user message plus the answer that closed it (no prior
20
+ tool calls, tool results, or worker notes). Use it as `FinalResultPolicy.synthesis_history` so a
21
+ synthesizer's input stays bounded across follow-up turns without losing their context.
22
+ - Orchestration: workers that end with `max_iterations` / `max_iterations_finalized` are reported to
23
+ the synthesizer as a separate completion fact (partial findings), next to error turns.
24
+
25
+ ### Fixed
26
+
27
+ - Design guide: `summarize_tool_result` was documented as a summarization knob; it actually ends
28
+ the run after the first tool batch. The agent topic now describes it and `stop_at_tools`.
29
+
30
+ ## [0.42.4] - 2026-10-05
31
+
32
+ ### Fixed
33
+
34
+ - Orchestration (spec 0066 follow-up): `PlanBasedOrchestrator`, `AIOrchestrator`,
35
+ `RoundRobinOrchestrator`, and `HandoffOrchestrator` now accept `name=` and `description=` and
36
+ forward them to `BaseOrchestrator`. Previously a team could not be named at construction, so
37
+ `response.source` was always the class name (e.g. `"PlanBasedOrchestrator"`) unless `name` was
38
+ set on the instance afterwards.
39
+
9
40
  ## [0.42.3] - 2026-10-05
10
41
 
11
42
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentbyte
3
- Version: 0.42.3
3
+ Version: 0.43.0
4
4
  Summary: A toolkit for designing multiagent systems
5
5
  Author-email: MrDataPsycho <mr.data.psycho@gmail.com>
6
6
  License-Expression: LicenseRef-Proprietary
@@ -77,7 +77,7 @@ Description-Content-Type: text/markdown
77
77
 
78
78
  Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
79
79
 
80
- Current release: **0.42.3**
80
+ Current release: **0.43.0**
81
81
 
82
82
  ## Building an Agent
83
83
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
4
4
 
5
- Current release: **0.42.3**
5
+ Current release: **0.43.0**
6
6
 
7
7
  ## Building an Agent
8
8
 
@@ -0,0 +1,2 @@
1
+ __version__ = "0.43.0"
2
+ VERSION = __version__
@@ -372,6 +372,14 @@ class Agent(BaseAgent):
372
372
  and working_context.get_approval_response(tool_call.call_id) is None
373
373
  )
374
374
 
375
+ def _is_stop_tool_success(self, item: object) -> bool:
376
+ """Whether *item* is a successful result of a ``stop_at_tools`` tool."""
377
+ return (
378
+ isinstance(item, ToolMessage)
379
+ and item.success
380
+ and item.tool_name in self.stop_at_tools
381
+ )
382
+
375
383
  async def _resolve_tool_batch(
376
384
  self,
377
385
  working_context: AgentContext,
@@ -560,6 +568,7 @@ class Agent(BaseAgent):
560
568
  # not-yet-run siblings, in order) before asking the model again.
561
569
  if self._unresolved_tail_calls(working_context):
562
570
  outcome: dict[str, int | bool] = {"executed": 0, "paused": False}
571
+ stop_tool_succeeded = False
563
572
  async for item in self._resolve_tool_batch(
564
573
  working_context,
565
574
  cancellation_token,
@@ -567,11 +576,15 @@ class Agent(BaseAgent):
567
576
  provider_tools,
568
577
  outcome,
569
578
  ):
579
+ stop_tool_succeeded |= self._is_stop_tool_success(item)
570
580
  yield item
571
581
  tool_calls += int(outcome["executed"])
572
582
  if outcome["paused"]:
573
583
  finish_reason = "approval_needed"
574
584
  break
585
+ if stop_tool_succeeded:
586
+ finish_reason = "tool_executed"
587
+ break
575
588
 
576
589
  llm_messages = await self._prepare_llm_messages([], working_context, extra_instructions=extra_instructions)
577
590
  if self.memory is not None:
@@ -773,6 +786,7 @@ class Agent(BaseAgent):
773
786
  break
774
787
 
775
788
  outcome = {"executed": 0, "paused": False}
789
+ stop_tool_succeeded = False
776
790
  async for item in self._resolve_tool_batch(
777
791
  working_context,
778
792
  cancellation_token,
@@ -780,13 +794,14 @@ class Agent(BaseAgent):
780
794
  provider_tools,
781
795
  outcome,
782
796
  ):
797
+ stop_tool_succeeded |= self._is_stop_tool_success(item)
783
798
  yield item
784
799
  tool_calls += int(outcome["executed"])
785
800
  if outcome["paused"]:
786
801
  finish_reason = "approval_needed"
787
802
  break
788
803
 
789
- if not self.summarize_tool_result:
804
+ if stop_tool_succeeded or not self.summarize_tool_result:
790
805
  finish_reason = "tool_executed"
791
806
  break
792
807
 
@@ -59,6 +59,7 @@ class BaseAgent(ABC):
59
59
  required_tools: Optional[List[str]] = None,
60
60
  example_tasks: Optional[List[str]] = None,
61
61
  context_providers: Optional[List[ContextProvider]] = None,
62
+ stop_at_tools: Optional[List[str]] = None,
62
63
  **kwargs: Any,
63
64
  ) -> None:
64
65
  """Initialize the agent.
@@ -69,6 +70,15 @@ class BaseAgent(ABC):
69
70
  ``max_iterations >= 2``: with ``max_iterations=1`` the only turn keeps
70
71
  its tools, so a run that calls a tool ends with
71
72
  ``finish_reason="max_iterations"`` and no final answer.
73
+
74
+ ``summarize_tool_result=False`` ends the run right after the first tool
75
+ batch executes, with no further model call
76
+ (``finish_reason="tool_executed"``). ``stop_at_tools`` is the selective
77
+ form: the agent keeps its tool loop (multi-step discovery, retries after a
78
+ failed call) and ends the same way once a call to one of the named tools
79
+ succeeds. The names must be the agent's own tools. Use either when another
80
+ component, such as an orchestrator's synthesizer, writes the answer from
81
+ the raw tool results.
72
82
  """
73
83
  self.name = name
74
84
  self.description = description
@@ -84,6 +94,7 @@ class BaseAgent(ABC):
84
94
  self.required_tools = required_tools or []
85
95
  self.example_tasks = example_tasks or []
86
96
  self.context_providers: List[ContextProvider] = list(context_providers) if context_providers else []
97
+ self.stop_at_tools: List[str] = list(stop_at_tools) if stop_at_tools else []
87
98
  self.extra_config = kwargs
88
99
 
89
100
  self._validate_configuration()
@@ -100,6 +111,13 @@ class BaseAgent(ABC):
100
111
  raise AgentConfigurationError("Model client is required")
101
112
  if self.max_iterations <= 0:
102
113
  raise AgentConfigurationError("max_iterations must be > 0")
114
+ tool_names = {tool.name for tool in self.tools}
115
+ unknown = [name for name in self.stop_at_tools if name not in tool_names]
116
+ if unknown:
117
+ raise AgentConfigurationError(
118
+ f"stop_at_tools names unknown tools {unknown}; "
119
+ f"available: {sorted(tool_names)}"
120
+ )
103
121
 
104
122
  def _process_tools(self, tools: List[Union[BaseTool, Callable]]) -> List[BaseTool]:
105
123
  """Normalize mixed tool list into BaseTool instances."""
@@ -54,11 +54,15 @@ class AIOrchestrator(BaseOrchestrator):
54
54
  history_policy: HistoryContextPolicy | None = None,
55
55
  selector_policy: SelectorContextPolicy | None = None,
56
56
  final_result_policy: FinalResultPolicy | None = None,
57
+ name: str | None = None,
58
+ description: str | None = None,
57
59
  ):
58
60
  super().__init__(
59
61
  agents,
60
62
  termination,
61
63
  max_iterations,
64
+ name=name,
65
+ description=description,
62
66
  history_policy=history_policy,
63
67
  final_result_policy=final_result_policy,
64
68
  )
@@ -51,6 +51,8 @@ _SYNTHESIS_INSTRUCTION = (
51
51
  )
52
52
  _SYNTHESIS_SELECTION_REASON = "Synthesis"
53
53
  _SYNTHESIS_FAILED_FINISH_REASONS = frozenset({"error", "approval_needed", "cancelled"})
54
+ # A worker that hit its iteration budget returned at most a partial result.
55
+ _EXHAUSTED_FINISH_REASONS = frozenset({"max_iterations", "max_iterations_finalized"})
54
56
 
55
57
  # Stop source -> agent finish_reason (spec 0066); every other source, termination
56
58
  # conditions included, maps to "stop".
@@ -128,6 +130,7 @@ class BaseOrchestrator(ABC):
128
130
 
129
131
  # Runtime state
130
132
  self.shared_messages: List[Message] = []
133
+ self._run_start_index = 0
131
134
  self.iteration_count = 0
132
135
  self.start_time: Optional[float] = None
133
136
  self._last_termination_check_count = 0
@@ -154,6 +157,7 @@ class BaseOrchestrator(ABC):
154
157
  self._turn_usage: list[tuple[str, Usage]] = []
155
158
  self._run_task_messages: list[Message] = []
156
159
  self._worker_error_agents: list[str] = []
160
+ self._worker_exhausted_agents: list[str] = []
157
161
  self._synthesis_usage: Usage | None = None
158
162
  self._synthesis_message: Message | None = None
159
163
  self._synthesis_meta: dict[str, Any] | None = None
@@ -307,6 +311,10 @@ class BaseOrchestrator(ABC):
307
311
  # Seed shared_messages from prior session history when context is provided
308
312
  if context is not None and context.messages:
309
313
  self.shared_messages.extend(list(context.messages))
314
+ # Where this run's messages begin; earlier ones are prior session turns.
315
+ self._run_start_index = len(self.shared_messages) - (
316
+ len(initial_messages) if task_in_context else 0
317
+ )
310
318
 
311
319
  # Initialize stop_message
312
320
  stop_message: Optional[StopMessage] = None
@@ -419,6 +427,8 @@ class BaseOrchestrator(ABC):
419
427
  if self._synthesizer is not None:
420
428
  if result.finish_reason == "error":
421
429
  self._worker_error_agents.append(next_agent.name)
430
+ elif result.finish_reason in _EXHAUSTED_FINISH_REASONS:
431
+ self._worker_exhausted_agents.append(next_agent.name)
422
432
  approval_stop = self._get_approval_stop_message(next_agent, result)
423
433
  if approval_stop is not None:
424
434
  # Synthesis cannot resolve a pending approval; stop here.
@@ -888,6 +898,12 @@ class BaseOrchestrator(ABC):
888
898
  "- Worker turns that ended in an error: "
889
899
  + ", ".join(dict.fromkeys(self._worker_error_agents))
890
900
  )
901
+ if self._worker_exhausted_agents:
902
+ facts.append(
903
+ "- Worker turns that ran out of iterations before completing (treat their "
904
+ "findings as partial): "
905
+ + ", ".join(dict.fromkeys(self._worker_exhausted_agents))
906
+ )
891
907
  facts.extend(f"- {fact}" for fact in self._get_synthesis_facts())
892
908
  return (
893
909
  f"Original request:\n{request}\n\n"
@@ -1057,7 +1073,9 @@ class BaseOrchestrator(ABC):
1057
1073
  self._last_context_was_text = False
1058
1074
  self._turn_usage = []
1059
1075
  self._run_task_messages = []
1076
+ self._run_start_index = 0
1060
1077
  self._worker_error_agents = []
1078
+ self._worker_exhausted_agents = []
1061
1079
  self._synthesis_usage = None
1062
1080
  self._synthesis_message = None
1063
1081
  self._synthesis_meta = None
@@ -1260,8 +1278,40 @@ class BaseOrchestrator(ABC):
1260
1278
  """Return the relevant shared-message slice for a history policy."""
1261
1279
  if policy.window == "recent" and policy.message_limit is not None:
1262
1280
  return self._select_recent_messages(policy.message_limit)
1281
+ if policy.window == "run":
1282
+ prior = self.shared_messages[: self._run_start_index]
1283
+ return [
1284
+ *self._condense_prior_turns(prior),
1285
+ *self.shared_messages[self._run_start_index :],
1286
+ ]
1263
1287
  return list(self.shared_messages)
1264
1288
 
1289
+ @staticmethod
1290
+ def _condense_prior_turns(messages: list[Message]) -> list[Message]:
1291
+ """Each earlier turn as its user message(s) plus the answer that closed it.
1292
+
1293
+ The closing answer is the turn's last assistant message with content and
1294
+ no tool calls (for a team with a synthesizer, the synthesized answer).
1295
+ Tool calls, tool results, and intermediate replies are dropped.
1296
+ """
1297
+ condensed: list[Message] = []
1298
+ answer: Message | None = None
1299
+ for message in messages:
1300
+ if isinstance(message, UserMessage):
1301
+ if answer is not None:
1302
+ condensed.append(answer)
1303
+ answer = None
1304
+ condensed.append(message)
1305
+ elif (
1306
+ isinstance(message, AssistantMessage)
1307
+ and message.content
1308
+ and not message.tool_calls
1309
+ ):
1310
+ answer = message
1311
+ if answer is not None:
1312
+ condensed.append(answer)
1313
+ return condensed
1314
+
1265
1315
  def _select_recent_messages(self, message_limit: int) -> list[Message]:
1266
1316
  """Last `message_limit` messages, never splitting a tool-call exchange.
1267
1317
 
@@ -104,6 +104,8 @@ class HandoffOrchestrator(BaseOrchestrator):
104
104
  max_iterations: int = 50,
105
105
  history_policy: HistoryContextPolicy | None = None,
106
106
  final_result_policy: FinalResultPolicy | None = None,
107
+ name: str | None = None,
108
+ description: str | None = None,
107
109
  ):
108
110
  """
109
111
  Initialise the handoff orchestrator.
@@ -124,11 +126,15 @@ class HandoffOrchestrator(BaseOrchestrator):
124
126
  max_iterations: Safety cap on orchestration iterations.
125
127
  history_policy: History window/format configuration.
126
128
  final_result_policy: Final-message selection and finalization config.
129
+ name: Team name; reported as ``response.source`` (defaults to the class name).
130
+ description: Optional description of the team's purpose.
127
131
  """
128
132
  super().__init__(
129
133
  agents,
130
134
  termination,
131
135
  max_iterations,
136
+ name=name,
137
+ description=description,
132
138
  history_policy=history_policy,
133
139
  final_result_policy=final_result_policy,
134
140
  )
@@ -78,11 +78,15 @@ class PlanBasedOrchestrator(BaseOrchestrator):
78
78
  history_policy: HistoryContextPolicy | None = None,
79
79
  review_gate_policy: ReviewGatePolicy | None = None,
80
80
  final_result_policy: FinalResultPolicy | None = None,
81
+ name: str | None = None,
82
+ description: str | None = None,
81
83
  ):
82
84
  super().__init__(
83
85
  agents,
84
86
  termination,
85
87
  max_iterations,
88
+ name=name,
89
+ description=description,
86
90
  history_policy=history_policy,
87
91
  final_result_policy=final_result_policy,
88
92
  )
@@ -12,7 +12,11 @@ class AgentHistoryPolicy(BaseModel):
12
12
 
13
13
  model_config = ConfigDict(extra="forbid")
14
14
 
15
- window: Literal["full", "recent"]
15
+ window: Literal["full", "recent", "run"]
16
+ """``full``: the whole shared conversation. ``recent``: the last
17
+ ``message_limit`` messages. ``run``: this run's messages in full, with earlier
18
+ turns of the session condensed to each user message and the answer that
19
+ closed its turn (no tool calls, tool results, or intermediate replies)."""
16
20
  message_limit: int | None = None
17
21
  format: Literal["messages", "text", "markdown", "json"]
18
22
  include_turn_prompt: bool = True
@@ -32,11 +32,15 @@ class RoundRobinOrchestrator(BaseOrchestrator):
32
32
  max_iterations: int = 50,
33
33
  history_policy: HistoryContextPolicy | None = None,
34
34
  final_result_policy: FinalResultPolicy | None = None,
35
+ name: str | None = None,
36
+ description: str | None = None,
35
37
  ):
36
38
  super().__init__(
37
39
  agents,
38
40
  termination,
39
41
  max_iterations,
42
+ name=name,
43
+ description=description,
40
44
  history_policy=history_policy,
41
45
  final_result_policy=final_result_policy,
42
46
  )
@@ -79,6 +79,7 @@ class WorkflowAgent(BaseAgent):
79
79
  self.max_iterations = 1
80
80
  self.output_format = None
81
81
  self.summarize_tool_result = False
82
+ self.stop_at_tools = []
82
83
  self.required_tools = []
83
84
  self.example_tasks = list(workflow.config.metadata.get("example_tasks", []))
84
85
  self.extra_config = {}
@@ -0,0 +1,170 @@
1
+ """``stop_at_tools``: end the run, without a final model call, once a named tool succeeds."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import AsyncGenerator
6
+ from typing import Any
7
+
8
+ import pytest
9
+
10
+ from agentbyte.agents import Agent
11
+ from agentbyte.agents.base import AgentConfigurationError
12
+ from agentbyte.llm.base import BaseChatCompletionClient, BaseChatCompletionClientConfig
13
+ from agentbyte.llm.types import ChatCompletionChunk, ChatCompletionResult
14
+ from agentbyte.messages import AssistantMessage, ToolMessage, Usage, UserMessage
15
+
16
+
17
+ class _Config(BaseChatCompletionClientConfig):
18
+ pass
19
+
20
+
21
+ class FakeModelClient(BaseChatCompletionClient):
22
+ """Returns scripted completions in order."""
23
+
24
+ def __init__(self, responses: list[ChatCompletionResult]) -> None:
25
+ super().__init__(model="fake", client=object())
26
+ self._responses = list(responses)
27
+
28
+ async def create(self, messages, tools=None, output_format=None, **kwargs: Any) -> ChatCompletionResult:
29
+ return self._responses.pop(0)
30
+
31
+ async def create_stream(self, *args: Any, **kwargs: Any) -> AsyncGenerator[ChatCompletionChunk, None]:
32
+ yield ChatCompletionChunk(content="", model="fake", is_complete=True)
33
+
34
+ def _to_config(self) -> BaseChatCompletionClientConfig:
35
+ return _Config(model=self.model, config=self.config)
36
+
37
+ @classmethod
38
+ def _from_config(cls, config: BaseChatCompletionClientConfig) -> FakeModelClient:
39
+ return cls([])
40
+
41
+
42
+ def discover_schema() -> str:
43
+ """Return the table schema."""
44
+ return "orders(id, amount)"
45
+
46
+
47
+ def run_query(sql: str) -> str:
48
+ """Run a read-only SQL query."""
49
+ if sql == "bad":
50
+ raise ValueError("unknown column")
51
+ return "rows: 3"
52
+
53
+
54
+ def _calls(*calls: tuple[str, dict]) -> ChatCompletionResult:
55
+ return ChatCompletionResult(
56
+ message=AssistantMessage(
57
+ content="",
58
+ source="fake",
59
+ tool_calls=[
60
+ {"tool_name": name, "parameters": params, "call_id": f"c-{name}-{i}"}
61
+ for i, (name, params) in enumerate(calls)
62
+ ],
63
+ ),
64
+ usage=Usage(tokens_input=1, tokens_output=1),
65
+ model="fake",
66
+ )
67
+
68
+
69
+ def _answer(text: str) -> ChatCompletionResult:
70
+ return ChatCompletionResult(
71
+ message=AssistantMessage(content=text, source="fake"),
72
+ usage=Usage(tokens_input=1, tokens_output=1),
73
+ model="fake",
74
+ )
75
+
76
+
77
+ def _agent(client: FakeModelClient, **kwargs) -> Agent:
78
+ return Agent(
79
+ name="analyst",
80
+ description="desc",
81
+ instructions="help",
82
+ model_client=client,
83
+ tools=[discover_schema, run_query],
84
+ **kwargs,
85
+ )
86
+
87
+
88
+ @pytest.mark.asyncio
89
+ async def test_stops_after_multi_step_discovery_without_final_answer() -> None:
90
+ client = FakeModelClient(
91
+ [_calls(("discover_schema", {})), _calls(("run_query", {"sql": "ok"}))]
92
+ )
93
+ agent = _agent(client, stop_at_tools=["run_query"])
94
+
95
+ response = await agent.run(UserMessage(content="how many orders?", source="user"))
96
+
97
+ assert response.finish_reason == "tool_executed"
98
+ assert response.usage.llm_calls == 2
99
+ assert response.usage.tool_calls == 2
100
+ last = response.messages[-1]
101
+ assert isinstance(last, ToolMessage)
102
+ assert (last.tool_name, last.success, last.content) == ("run_query", True, "rows: 3")
103
+
104
+
105
+ @pytest.mark.asyncio
106
+ async def test_failed_stop_tool_does_not_stop_so_the_agent_can_retry() -> None:
107
+ client = FakeModelClient(
108
+ [_calls(("run_query", {"sql": "bad"})), _calls(("run_query", {"sql": "ok"}))]
109
+ )
110
+ agent = _agent(client, stop_at_tools=["run_query"])
111
+
112
+ response = await agent.run(UserMessage(content="how many orders?", source="user"))
113
+
114
+ assert response.finish_reason == "tool_executed"
115
+ results = [m for m in response.messages if isinstance(m, ToolMessage)]
116
+ assert [m.success for m in results] == [False, True]
117
+ assert response.usage.llm_calls == 2
118
+
119
+
120
+ @pytest.mark.asyncio
121
+ async def test_stop_tool_in_a_parallel_batch_runs_the_whole_batch() -> None:
122
+ client = FakeModelClient(
123
+ [_calls(("run_query", {"sql": "ok"}), ("discover_schema", {}))]
124
+ )
125
+ agent = _agent(client, stop_at_tools=["run_query"])
126
+
127
+ response = await agent.run(UserMessage(content="q", source="user"))
128
+
129
+ assert response.finish_reason == "tool_executed"
130
+ assert [m.tool_name for m in response.messages if isinstance(m, ToolMessage)] == [
131
+ "run_query",
132
+ "discover_schema",
133
+ ]
134
+
135
+
136
+ @pytest.mark.asyncio
137
+ async def test_without_a_stop_tool_call_the_agent_answers_normally() -> None:
138
+ client = FakeModelClient([_calls(("discover_schema", {})), _answer("no query needed")])
139
+ agent = _agent(client, stop_at_tools=["run_query"])
140
+
141
+ response = await agent.run(UserMessage(content="what tables exist?", source="user"))
142
+
143
+ assert response.finish_reason == "stop"
144
+ assert response.final_content == "no query needed"
145
+
146
+
147
+ @pytest.mark.asyncio
148
+ async def test_stop_tool_never_succeeding_finalizes_on_exhaustion() -> None:
149
+ client = FakeModelClient(
150
+ [
151
+ _calls(("run_query", {"sql": "bad"})),
152
+ _calls(("run_query", {"sql": "bad"})),
153
+ _answer("The query failed: unknown column."),
154
+ ]
155
+ )
156
+ agent = _agent(client, stop_at_tools=["run_query"], max_iterations=3)
157
+
158
+ response = await agent.run(UserMessage(content="q", source="user"))
159
+
160
+ assert response.finish_reason == "max_iterations_finalized"
161
+ assert response.final_content == "The query failed: unknown column."
162
+
163
+
164
+ def test_unknown_stop_tool_is_rejected() -> None:
165
+ with pytest.raises(AgentConfigurationError, match="run_qeury"):
166
+ _agent(FakeModelClient([]), stop_at_tools=["run_qeury"])
167
+
168
+
169
+ def test_stop_at_tools_defaults_to_empty() -> None:
170
+ assert _agent(FakeModelClient([])).stop_at_tools == []
@@ -123,26 +123,58 @@ def _never() -> TextMentionTermination:
123
123
  return TextMentionTermination("NEVER_SAID")
124
124
 
125
125
 
126
- def _team(pattern: str, *agents: BaseAgent, client: CoordinatorClient | None = None):
126
+ def _team(
127
+ pattern: str,
128
+ *agents: BaseAgent,
129
+ client: CoordinatorClient | None = None,
130
+ **identity: str,
131
+ ):
127
132
  members = list(agents) or [ScriptAgent("worker")]
128
133
  client = client or CoordinatorClient()
134
+ if not identity:
135
+ identity = {"name": "team"}
129
136
  if pattern == "round_robin":
130
- team = RoundRobinOrchestrator(members, _never(), max_iterations=1)
131
- elif pattern == "handoff":
132
- team = HandoffOrchestrator(members, _never(), max_iterations=1)
133
- elif pattern == "ai":
134
- team = AIOrchestrator(members, _never(), client, max_iterations=1)
135
- elif pattern == "plan":
136
- team = PlanBasedOrchestrator(members, _never(), client, max_iterations=1)
137
- else:
138
- raise AssertionError(pattern)
139
- team.name = "team"
140
- return team
137
+ return RoundRobinOrchestrator(members, _never(), max_iterations=1, **identity)
138
+ if pattern == "handoff":
139
+ return HandoffOrchestrator(members, _never(), max_iterations=1, **identity)
140
+ if pattern == "ai":
141
+ return AIOrchestrator(members, _never(), client, max_iterations=1, **identity)
142
+ if pattern == "plan":
143
+ return PlanBasedOrchestrator(members, _never(), client, max_iterations=1, **identity)
144
+ raise AssertionError(pattern)
141
145
 
142
146
 
143
147
  PATTERNS = ["round_robin", "handoff", "ai", "plan"]
144
148
 
145
149
 
150
+ _PATTERN_CLASSES = {
151
+ "round_robin": "RoundRobinOrchestrator",
152
+ "handoff": "HandoffOrchestrator",
153
+ "ai": "AIOrchestrator",
154
+ "plan": "PlanBasedOrchestrator",
155
+ }
156
+
157
+
158
+ @pytest.mark.asyncio
159
+ class TestTeamIdentity:
160
+ @pytest.mark.parametrize("pattern", PATTERNS)
161
+ async def test_name_and_description_are_constructor_arguments(self, pattern: str) -> None:
162
+ team = _team(pattern, name="procurement", description="Procurement specialists")
163
+
164
+ response = await team.run("fix it")
165
+
166
+ assert team.name == "procurement"
167
+ assert team.description == "Procurement specialists"
168
+ assert response.source == "procurement"
169
+
170
+ @pytest.mark.parametrize("pattern", PATTERNS)
171
+ async def test_name_defaults_to_class_name(self, pattern: str) -> None:
172
+ team = _team(pattern, description="unnamed")
173
+
174
+ assert team.name == _PATTERN_CLASSES[pattern]
175
+ assert team.description == "unnamed"
176
+
177
+
146
178
  @pytest.mark.asyncio
147
179
  class TestStreamInvariant:
148
180
  @pytest.mark.parametrize("pattern", PATTERNS)