fast-agent-mcp 0.2.14__tar.gz → 0.2.17__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.

Potentially problematic release.


This version of fast-agent-mcp might be problematic. Click here for more details.

Files changed (172) hide show
  1. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/PKG-INFO +4 -6
  2. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/README.md +3 -3
  3. {fast_agent_mcp-0.2.14/src/mcp_agent/resources → fast_agent_mcp-0.2.17}/examples/data-analysis/analysis-campaign.py +2 -2
  4. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/mcp/state-transfer/fastagent.config.yaml +1 -1
  5. {fast_agent_mcp-0.2.14/src/mcp_agent/resources → fast_agent_mcp-0.2.17}/examples/researcher/fastagent.config.yaml +1 -6
  6. {fast_agent_mcp-0.2.14/src/mcp_agent/resources → fast_agent_mcp-0.2.17}/examples/workflows/evaluator.py +1 -1
  7. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/fastagent.config.yaml +0 -1
  8. {fast_agent_mcp-0.2.14/src/mcp_agent/resources → fast_agent_mcp-0.2.17}/examples/workflows/orchestrator.py +7 -9
  9. {fast_agent_mcp-0.2.14/src/mcp_agent/resources → fast_agent_mcp-0.2.17}/examples/workflows/parallel.py +1 -1
  10. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/pyproject.toml +1 -4
  11. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/base_agent.py +50 -6
  12. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/orchestrator_agent.py +6 -7
  13. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/router_agent.py +70 -136
  14. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/app.py +1 -124
  15. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/commands/setup.py +1 -1
  16. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/config.py +19 -19
  17. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/context.py +4 -22
  18. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/agent_types.py +2 -2
  19. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/direct_decorators.py +2 -2
  20. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/direct_factory.py +2 -1
  21. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/enhanced_prompt.py +6 -5
  22. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/fastagent.py +1 -1
  23. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/interactive_prompt.py +70 -50
  24. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/request_params.py +5 -1
  25. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/executor/workflow_signal.py +0 -2
  26. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/augmented_llm.py +183 -57
  27. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/augmented_llm_passthrough.py +1 -1
  28. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/augmented_llm_playback.py +21 -1
  29. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/memory.py +3 -3
  30. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/model_factory.py +3 -1
  31. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/provider_key_manager.py +1 -0
  32. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/provider_types.py +2 -1
  33. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/augmented_llm_anthropic.py +49 -10
  34. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/augmented_llm_deepseek.py +0 -2
  35. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/augmented_llm_generic.py +4 -2
  36. fast_agent_mcp-0.2.17/src/mcp_agent/llm/providers/augmented_llm_google.py +30 -0
  37. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/augmented_llm_openai.py +95 -158
  38. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/multipart_converter_openai.py +10 -27
  39. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/sampling_converter_openai.py +5 -6
  40. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/interfaces.py +6 -1
  41. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/mcp_aggregator.py +2 -8
  42. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompt_message_multipart.py +25 -2
  43. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17/src/mcp_agent/resources}/examples/data-analysis/analysis-campaign.py +2 -2
  44. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/in_dev/agent_build.py +1 -1
  45. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/job.py +1 -1
  46. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +1 -1
  47. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/agent.py +0 -2
  48. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +2 -3
  49. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17/src/mcp_agent/resources}/examples/researcher/fastagent.config.yaml +1 -6
  50. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -1
  51. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17/src/mcp_agent/resources}/examples/workflows/parallel.py +1 -1
  52. fast_agent_mcp-0.2.14/src/mcp_agent/executor/decorator_registry.py +0 -112
  53. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/.gitignore +0 -0
  54. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/LICENSE +0 -0
  55. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/data-analysis/analysis.py +0 -0
  56. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/data-analysis/fastagent.config.yaml +0 -0
  57. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  58. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/mcp/state-transfer/agent_one.py +0 -0
  59. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/mcp/state-transfer/agent_two.py +0 -0
  60. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/researcher/researcher-eval.py +0 -0
  61. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/researcher/researcher-imp.py +0 -0
  62. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/researcher/researcher.py +0 -0
  63. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/chaining.py +0 -0
  64. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/graded_report.md +0 -0
  65. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/human_input.py +0 -0
  66. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/router.py +0 -0
  67. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/short_story.md +0 -0
  68. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/examples/workflows/short_story.txt +0 -0
  69. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/__init__.py +0 -0
  70. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/__init__.py +0 -0
  71. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/agent.py +0 -0
  72. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/__init__.py +0 -0
  73. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/chain_agent.py +0 -0
  74. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/evaluator_optimizer.py +0 -0
  75. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/orchestrator_models.py +0 -0
  76. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/orchestrator_prompts.py +0 -0
  77. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/agents/workflow/parallel_agent.py +0 -0
  78. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/__init__.py +0 -0
  79. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/__main__.py +0 -0
  80. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/commands/check_config.py +0 -0
  81. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/commands/quickstart.py +0 -0
  82. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/main.py +0 -0
  83. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/cli/terminal.py +0 -0
  84. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/console.py +0 -0
  85. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/context_dependent.py +0 -0
  86. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/__init__.py +0 -0
  87. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/agent_app.py +0 -0
  88. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/error_handling.py +0 -0
  89. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/exceptions.py +0 -0
  90. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/mcp_content.py +0 -0
  91. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/prompt.py +0 -0
  92. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/core/validation.py +0 -0
  93. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/event_progress.py +0 -0
  94. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/executor/__init__.py +0 -0
  95. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/executor/executor.py +0 -0
  96. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/executor/task_registry.py +0 -0
  97. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/human_input/__init__.py +0 -0
  98. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/human_input/handler.py +0 -0
  99. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/human_input/types.py +0 -0
  100. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/__init__.py +0 -0
  101. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/prompt_utils.py +0 -0
  102. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/__init__.py +0 -0
  103. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/anthropic_utils.py +0 -0
  104. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/augmented_llm_openrouter.py +0 -0
  105. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/multipart_converter_anthropic.py +0 -0
  106. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/openai_multipart.py +0 -0
  107. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/openai_utils.py +0 -0
  108. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -0
  109. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/sampling_converter.py +0 -0
  110. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/llm/sampling_format_converter.py +0 -0
  111. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/__init__.py +0 -0
  112. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/events.py +0 -0
  113. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/json_serializer.py +0 -0
  114. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/listeners.py +0 -0
  115. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/logger.py +0 -0
  116. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/rich_progress.py +0 -0
  117. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/tracing.py +0 -0
  118. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/logging/transport.py +0 -0
  119. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/__init__.py +0 -0
  120. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/gen_client.py +0 -0
  121. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/helpers/__init__.py +0 -0
  122. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/helpers/content_helpers.py +0 -0
  123. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/logger_textio.py +0 -0
  124. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/mcp_agent_client_session.py +0 -0
  125. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/mcp_connection_manager.py +0 -0
  126. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/mime_utils.py +0 -0
  127. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompt_render.py +0 -0
  128. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompt_serialization.py +0 -0
  129. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
  130. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
  131. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/prompt_constants.py +0 -0
  132. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/prompt_helpers.py +0 -0
  133. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/prompt_load.py +0 -0
  134. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/prompt_server.py +0 -0
  135. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/prompts/prompt_template.py +0 -0
  136. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/resource_utils.py +0 -0
  137. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp/sampling.py +0 -0
  138. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp_server/__init__.py +0 -0
  139. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp_server/agent_server.py +0 -0
  140. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/mcp_server_registry.py +0 -0
  141. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/progress_display.py +0 -0
  142. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
  143. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  144. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  145. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/in_dev/css-LICENSE.txt +0 -0
  146. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/in_dev/slides.py +0 -0
  147. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
  148. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
  149. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/history_transfer.py +0 -0
  150. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/prompt_category.py +0 -0
  151. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +0 -0
  152. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/simple.txt +0 -0
  153. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/sizer.py +0 -0
  154. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/internal/social.py +0 -0
  155. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_one.py +0 -0
  156. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_two.py +0 -0
  157. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
  158. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/__init__.py +0 -0
  159. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/delimited_prompt.txt +0 -0
  160. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/image_server.py +0 -0
  161. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/prompt1.txt +0 -0
  162. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/prompting/work_with_image.py +0 -0
  163. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +0 -0
  164. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +0 -0
  165. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
  166. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
  167. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17/src/mcp_agent/resources}/examples/workflows/evaluator.py +0 -0
  168. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
  169. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17/src/mcp_agent/resources}/examples/workflows/orchestrator.py +0 -0
  170. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
  171. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/resources/examples/workflows/short_story.txt +0 -0
  172. {fast_agent_mcp-0.2.14 → fast_agent_mcp-0.2.17}/src/mcp_agent/ui/console_display.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.2.14
3
+ Version: 0.2.17
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
6
6
  License: Apache License
@@ -237,8 +237,6 @@ Requires-Dist: ruff>=0.8.4; extra == 'dev'
237
237
  Requires-Dist: tomli>=2.2.1; extra == 'dev'
238
238
  Provides-Extra: openai
239
239
  Requires-Dist: openai>=1.58.1; extra == 'openai'
240
- Provides-Extra: temporal
241
- Requires-Dist: temporalio>=1.8.0; extra == 'temporal'
242
240
  Description-Content-Type: text/markdown
243
241
 
244
242
  <p align="center">
@@ -255,7 +253,7 @@ Description-Content-Type: text/markdown
255
253
  > [!TIP]
256
254
  > Documentation site is in production here : https://fast-agent.ai. Feel free to feed back what's helpful and what's not. llms.txt link is here: https://fast-agent.ai/llms.txt
257
255
 
258
- **`fast-agent`** enables you to create and interact with sophisticated Agents and Workflows in minutes. It is the first framework with complete, end-to-end tested MCP Feature support including Sampling. Both Anthropic (Haiku, Sonnet, Opus) and OpenAI models (gpt-4o family, o1/o3 family) are supported.
256
+ **`fast-agent`** enables you to create and interact with sophisticated Agents and Workflows in minutes. It is the first framework with complete, end-to-end tested MCP Feature support including Sampling. Both Anthropic (Haiku, Sonnet, Opus) and OpenAI models (gpt-4o/gpt-4.1 family, o1/o3 family) are supported.
259
257
 
260
258
  The simple declarative syntax lets you concentrate on composing your Prompts and MCP Servers to [build effective agents](https://www.anthropic.com/research/building-effective-agents).
261
259
 
@@ -313,7 +311,7 @@ Or start an interactive chat with the Agent:
313
311
 
314
312
  ```python
315
313
  async with fast.run() as agent:
316
- await agent()
314
+ await agent.interactive()
317
315
  ```
318
316
 
319
317
  Here is the complete `sizer.py` Agent application, with boilerplate code:
@@ -330,7 +328,7 @@ fast = FastAgent("Agent Example")
330
328
  )
331
329
  async def main():
332
330
  async with fast.run() as agent:
333
- await agent()
331
+ await agent.interactive()
334
332
 
335
333
  if __name__ == "__main__":
336
334
  asyncio.run(main())
@@ -12,7 +12,7 @@
12
12
  > [!TIP]
13
13
  > Documentation site is in production here : https://fast-agent.ai. Feel free to feed back what's helpful and what's not. llms.txt link is here: https://fast-agent.ai/llms.txt
14
14
 
15
- **`fast-agent`** enables you to create and interact with sophisticated Agents and Workflows in minutes. It is the first framework with complete, end-to-end tested MCP Feature support including Sampling. Both Anthropic (Haiku, Sonnet, Opus) and OpenAI models (gpt-4o family, o1/o3 family) are supported.
15
+ **`fast-agent`** enables you to create and interact with sophisticated Agents and Workflows in minutes. It is the first framework with complete, end-to-end tested MCP Feature support including Sampling. Both Anthropic (Haiku, Sonnet, Opus) and OpenAI models (gpt-4o/gpt-4.1 family, o1/o3 family) are supported.
16
16
 
17
17
  The simple declarative syntax lets you concentrate on composing your Prompts and MCP Servers to [build effective agents](https://www.anthropic.com/research/building-effective-agents).
18
18
 
@@ -70,7 +70,7 @@ Or start an interactive chat with the Agent:
70
70
 
71
71
  ```python
72
72
  async with fast.run() as agent:
73
- await agent()
73
+ await agent.interactive()
74
74
  ```
75
75
 
76
76
  Here is the complete `sizer.py` Agent application, with boilerplate code:
@@ -87,7 +87,7 @@ fast = FastAgent("Agent Example")
87
87
  )
88
88
  async def main():
89
89
  async with fast.run() as agent:
90
- await agent()
90
+ await agent.interactive()
91
91
 
92
92
  if __name__ == "__main__":
93
93
  asyncio.run(main())
@@ -33,7 +33,7 @@ Extract key insights that would be compelling for a social media campaign.
33
33
  - Extracted compelling insights suitable for social media promotion
34
34
  """,
35
35
  request_params=RequestParams(maxTokens=8192),
36
- model="gpt-4o",
36
+ model="gpt-4.1",
37
37
  )
38
38
  @fast.evaluator_optimizer(
39
39
  "analysis_tool",
@@ -55,7 +55,7 @@ Extract key insights that would be compelling for a social media campaign.
55
55
  """,
56
56
  servers=["fetch", "brave"], # Using the fetch MCP server for Brave search
57
57
  request_params=RequestParams(temperature=0.3),
58
- model="gpt-4o",
58
+ model="gpt-4.1",
59
59
  )
60
60
  # Social media content generator
61
61
  @fast.agent(
@@ -5,7 +5,7 @@
5
5
  # Check here for current details: https://fast-agent.ai/models/
6
6
 
7
7
  # set the default model for fast-agent below:
8
- default_model: gpt-4o
8
+ default_model: gpt-4.1
9
9
 
10
10
  # Logging and Console Configuration:
11
11
  logger:
@@ -4,7 +4,6 @@
4
4
  #
5
5
  #
6
6
 
7
- execution_engine: asyncio
8
7
  logger:
9
8
  type: console
10
9
  level: error
@@ -53,14 +52,10 @@ mcp:
53
52
  args: ["mcp-server-fetch"]
54
53
  sequential:
55
54
  command: "npx"
56
- args: ["-y","@modelcontextprotocol/server-sequential-thinking"]
57
-
55
+ args: ["-y", "@modelcontextprotocol/server-sequential-thinking"]
58
56
  # webmcp:
59
57
  # command: "node"
60
58
  # args: ["/home/ssmith/.webmcp/server.cjs"]
61
59
  # env:
62
60
  # WEBMCP_SERVER_TOKEN: 96e22896d8143fc1d61fec09208fc5ed
63
61
 
64
-
65
-
66
-
@@ -40,7 +40,7 @@ fast = FastAgent("Evaluator-Optimizer")
40
40
  Summarize your evaluation as a structured response with:
41
41
  - Overall quality rating.
42
42
  - Specific feedback and areas for improvement.""",
43
- model="gpt-4o",
43
+ model="gpt-4.1",
44
44
  )
45
45
  # Define the evaluator-optimizer workflow
46
46
  @fast.evaluator_optimizer(
@@ -3,7 +3,6 @@
3
3
  #
4
4
  #
5
5
 
6
- execution_engine: asyncio
7
6
  logger:
8
7
  type: file
9
8
  level: error
@@ -13,7 +13,7 @@ fast = FastAgent("Orchestrator-Workers")
13
13
  @fast.agent(
14
14
  "author",
15
15
  instruction="""You are to role play a poorly skilled writer,
16
- who makes frequent grammar, punctuations and spelling errors. You enjoy
16
+ who makes frequent grammar, punctuation and spelling errors. You enjoy
17
17
  writing short stories, but the narrative doesn't always make sense""",
18
18
  servers=["filesystem"],
19
19
  )
@@ -25,7 +25,7 @@ fast = FastAgent("Orchestrator-Workers")
25
25
  the closest match to a user's request, make the appropriate tool calls,
26
26
  and return the URI and CONTENTS of the closest match.""",
27
27
  servers=["fetch", "filesystem"],
28
- model="gpt-4o",
28
+ model="gpt-4.1",
29
29
  )
30
30
  @fast.agent(
31
31
  name="writer",
@@ -40,19 +40,17 @@ fast = FastAgent("Orchestrator-Workers")
40
40
  Identify any awkward phrasing or structural issues that could improve clarity.
41
41
  Provide detailed feedback on corrections.""",
42
42
  servers=["fetch"],
43
- model="gpt-4o",
43
+ model="gpt-4.1",
44
44
  )
45
45
  # Define the orchestrator to coordinate the other agents
46
46
  @fast.orchestrator(
47
- name="orchestrate",
48
- agents=["finder", "writer", "proofreader"],
49
- plan_type="full",
47
+ name="orchestrate", agents=["finder", "writer", "proofreader"], plan_type="full", model="sonnet"
50
48
  )
51
49
  async def main() -> None:
52
50
  async with fast.run() as agent:
53
- await agent.author(
54
- "write a 250 word short story about kittens discovering a castle, and save it to short_story.md"
55
- )
51
+ # await agent.author(
52
+ # "write a 250 word short story about kittens discovering a castle, and save it to short_story.md"
53
+ # )
56
54
 
57
55
  # The orchestrator can be used just like any other agent
58
56
  task = """Load the student's short story from short_story.md,
@@ -25,7 +25,7 @@ fast = FastAgent(
25
25
  instruction="""Verify the factual consistency within the story. Identify any contradictions,
26
26
  logical inconsistencies, or inaccuracies in the plot, character actions, or setting.
27
27
  Highlight potential issues with reasoning or coherence.""",
28
- model="gpt-4o",
28
+ model="gpt-4.1",
29
29
  )
30
30
  @fast.agent(
31
31
  name="style_enforcer",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fast-agent-mcp"
3
- version = "0.2.14"
3
+ version = "0.2.17"
4
4
  description = "Define, Prompt and Test MCP enabled Agents and Workflows"
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -34,9 +34,6 @@ dependencies = [
34
34
  ]
35
35
 
36
36
  [project.optional-dependencies]
37
- temporal = [
38
- "temporalio>=1.8.0",
39
- ]
40
37
  openai = [
41
38
  "openai>=1.58.1",
42
39
  ]
@@ -20,6 +20,7 @@ from typing import (
20
20
  Union,
21
21
  )
22
22
 
23
+ from a2a_types.types import AgentCapabilities, AgentCard, AgentSkill
23
24
  from mcp.types import (
24
25
  CallToolResult,
25
26
  EmbeddedResource,
@@ -58,6 +59,11 @@ if TYPE_CHECKING:
58
59
  from mcp_agent.context import Context
59
60
 
60
61
 
62
+ DEFAULT_CAPABILITIES = AgentCapabilities(
63
+ streaming=False, pushNotifications=False, stateTransitionHistory=False
64
+ )
65
+
66
+
61
67
  class BaseAgent(MCPAggregator, AgentProtocol):
62
68
  """
63
69
  A base Agent class that implements the AgentProtocol interface.
@@ -586,7 +592,7 @@ class BaseAgent(MCPAggregator, AgentProtocol):
586
592
 
587
593
  async def structured(
588
594
  self,
589
- prompt: List[PromptMessageMultipart],
595
+ multipart_messages: List[PromptMessageMultipart],
590
596
  model: Type[ModelT],
591
597
  request_params: RequestParams | None = None,
592
598
  ) -> Tuple[ModelT | None, PromptMessageMultipart]:
@@ -603,7 +609,7 @@ class BaseAgent(MCPAggregator, AgentProtocol):
603
609
  An instance of the specified model, or None if coercion fails
604
610
  """
605
611
  assert self._llm
606
- return await self._llm.structured(prompt, model, request_params)
612
+ return await self._llm.structured(multipart_messages, model, request_params)
607
613
 
608
614
  async def apply_prompt_messages(
609
615
  self, prompts: List[PromptMessageMultipart], request_params: RequestParams | None = None
@@ -626,13 +632,51 @@ class BaseAgent(MCPAggregator, AgentProtocol):
626
632
  def agent_type(self) -> AgentType:
627
633
  """
628
634
  Return the type of this agent.
635
+ """
636
+ return AgentType.BASIC
637
+
638
+ async def agent_card(self) -> AgentCard:
639
+ """
640
+ Return an A2A card describing this Agent
641
+ """
629
642
 
630
- This is used for display purposes in the interactive prompt and other UI elements.
643
+ skills: List[AgentSkill] = []
644
+ tools: ListToolsResult = await self.list_tools()
645
+ for tool in tools.tools:
646
+ skills.append(await self.convert(tool))
631
647
 
632
- Returns:
633
- String representing the agent type
648
+ return AgentCard(
649
+ name=self.name,
650
+ description=self.instruction,
651
+ url=f"fast-agent://agents/{self.name}/",
652
+ version="0.1",
653
+ capabilities=DEFAULT_CAPABILITIES,
654
+ defaultInputModes=["text/plain"],
655
+ defaultOutputModes=["text/plain"],
656
+ provider=None,
657
+ documentationUrl=None,
658
+ authentication=None,
659
+ skills=skills,
660
+ )
661
+
662
+ async def convert(self, tool: Tool) -> AgentSkill:
634
663
  """
635
- return AgentType.BASIC
664
+ Convert a Tool to an AgentSkill.
665
+ """
666
+
667
+ _, tool_without_namespace = await self._parse_resource_name(tool.name, "tool")
668
+ return AgentSkill(
669
+ id=tool.name,
670
+ name=tool_without_namespace,
671
+ description=tool.description,
672
+ tags=["tool"],
673
+ examples=None,
674
+ inputModes=None, # ["text/plain"],
675
+ # cover TextContent | ImageContent ->
676
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/223
677
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/93
678
+ outputModes=None, # ,["text/plain", "image/*"],
679
+ )
636
680
 
637
681
  @property
638
682
  def message_history(self) -> List[PromptMessageMultipart]:
@@ -57,6 +57,7 @@ class OrchestratorAgent(BaseAgent):
57
57
  config: AgentConfig,
58
58
  agents: List[Agent],
59
59
  plan_type: Literal["full", "iterative"] = "full",
60
+ plan_iterations: int = 5,
60
61
  context: Optional[Any] = None,
61
62
  **kwargs,
62
63
  ) -> None:
@@ -83,7 +84,7 @@ class OrchestratorAgent(BaseAgent):
83
84
  agent_name = agent.name
84
85
  self.logger.info(f"Adding agent '{agent_name}' to orchestrator")
85
86
  self.agents[agent_name] = agent
86
-
87
+ self.plan_iterations = plan_iterations
87
88
  # For tracking state during execution
88
89
  self.plan_result: Optional[PlanResult] = None
89
90
 
@@ -186,8 +187,8 @@ class OrchestratorAgent(BaseAgent):
186
187
  """
187
188
  iterations = 0
188
189
  total_steps_executed = 0
189
- max_iterations = request_params.max_iterations
190
- max_steps = getattr(request_params, "max_steps", max_iterations * 5)
190
+ max_iterations = self.plan_iterations
191
+ max_steps = getattr(request_params, "max_steps", max_iterations * 3)
191
192
 
192
193
  # Initialize plan result
193
194
  plan_result = PlanResult(objective=objective, step_results=[])
@@ -414,7 +415,7 @@ class OrchestratorAgent(BaseAgent):
414
415
  plan_status = "Plan Status: Not Started"
415
416
 
416
417
  # Calculate iteration information
417
- max_iterations = request_params.max_iterations
418
+ max_iterations = self.plan_iterations
418
419
  current_iteration = len(plan_result.step_results)
419
420
  current_iteration = min(current_iteration, max_iterations - 1)
420
421
  iterations_remaining = max(0, max_iterations - current_iteration - 1)
@@ -536,9 +537,7 @@ class OrchestratorAgent(BaseAgent):
536
537
  return ""
537
538
 
538
539
  # Get agent instruction or default description
539
- instruction = (
540
- agent.instruction if hasattr(agent, "instruction") else f"Agent '{agent_name}'"
541
- )
540
+ instruction = agent.instruction if agent.instruction else f"Agent '{agent_name}'"
542
541
 
543
542
  # Format with XML tags
544
543
  return f'<fastagent:agent name="{agent_name}">{instruction}</fastagent:agent>'
@@ -5,9 +5,8 @@ This provides a simplified implementation that routes messages to agents
5
5
  by determining the best agent for a request and dispatching to it.
6
6
  """
7
7
 
8
- from typing import TYPE_CHECKING, List, Optional, Tuple, Type
8
+ from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Type
9
9
 
10
- from mcp.types import TextContent
11
10
  from pydantic import BaseModel
12
11
 
13
12
  from mcp_agent.agents.agent import Agent
@@ -17,10 +16,12 @@ from mcp_agent.core.exceptions import AgentConfigError
17
16
  from mcp_agent.core.prompt import Prompt
18
17
  from mcp_agent.core.request_params import RequestParams
19
18
  from mcp_agent.logging.logger import get_logger
20
- from mcp_agent.mcp.interfaces import ModelT
19
+ from mcp_agent.mcp.interfaces import AugmentedLLMProtocol, ModelT
21
20
  from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
22
21
 
23
22
  if TYPE_CHECKING:
23
+ from a2a_types.types import AgentCard
24
+
24
25
  from mcp_agent.context import Context
25
26
 
26
27
  logger = get_logger(__name__)
@@ -36,47 +37,17 @@ Follow these guidelines:
36
37
  - Provide your confidence level (high, medium, low) and brief reasoning for your selection
37
38
  """
38
39
 
39
- # Default routing instruction with placeholders for context and request
40
+ # Default routing instruction with placeholders for context (AgentCard JSON)
40
41
  DEFAULT_ROUTING_INSTRUCTION = """
41
- You are a highly accurate request router that directs incoming requests to the most appropriate agent.
42
-
43
- <fastagent:data>
42
+ Select from the following agents to handle the request:
44
43
  <fastagent:agents>
44
+ [
45
45
  {context}
46
+ ]
46
47
  </fastagent:agents>
47
48
 
48
- <fastagent:request>
49
- {request}
50
- </fastagent:request>
51
- </fastagent:data>
52
-
53
- Your task is to analyze the request and determine the most appropriate agent from the options above.
54
-
55
- <fastagent:instruction>
56
- Respond with JSON following the schema below:
57
- {{
58
- "type": "object",
59
- "required": ["agent", "confidence", "reasoning"],
60
- "properties": {{
61
- "agent": {{
62
- "type": "string",
63
- "description": "The exact name of the selected agent"
64
- }},
65
- "confidence": {{
66
- "type": "string",
67
- "enum": ["high", "medium", "low"],
68
- "description": "Your confidence level in this selection"
69
- }},
70
- "reasoning": {{
71
- "type": "string",
72
- "description": "Brief explanation for your selection"
73
- }}
74
- }}
75
- }}
76
-
77
- Supply only the JSON with no preamble. Use "reasoning" field to describe actions. NEVER EMIT CODE FENCES.
78
-
79
- </fastagent:instruction>
49
+ You must respond with the 'name' of one of the agents listed above.
50
+
80
51
  """
81
52
 
82
53
 
@@ -85,18 +56,7 @@ class RoutingResponse(BaseModel):
85
56
 
86
57
  agent: str
87
58
  confidence: str
88
- reasoning: Optional[str] = None
89
-
90
-
91
- class RouterResult(BaseModel):
92
- """Router result with agent reference and confidence rating."""
93
-
94
- result: BaseAgent
95
- confidence: str
96
- reasoning: Optional[str] = None
97
-
98
- # Allow Agent objects to be stored without serialization
99
- model_config = {"arbitrary_types_allowed": True}
59
+ reasoning: str | None = None
100
60
 
101
61
 
102
62
  class RouterAgent(BaseAgent):
@@ -142,9 +102,7 @@ class RouterAgent(BaseAgent):
142
102
  # Set up base router request parameters
143
103
  base_params = {"systemPrompt": ROUTING_SYSTEM_INSTRUCTION, "use_history": False}
144
104
 
145
- # Merge with provided defaults if any
146
105
  if default_request_params:
147
- # Start with defaults and override with router-specific settings
148
106
  merged_params = default_request_params.model_copy(update=base_params)
149
107
  else:
150
108
  merged_params = RequestParams(**base_params)
@@ -174,32 +132,16 @@ class RouterAgent(BaseAgent):
174
132
  except Exception as e:
175
133
  logger.warning(f"Error shutting down agent: {str(e)}")
176
134
 
177
- async def _get_routing_result(
135
+ async def attach_llm(
178
136
  self,
179
- messages: List[PromptMessageMultipart],
180
- ) -> Optional[RouterResult]:
181
- """
182
- Common method to extract request and get routing result.
183
-
184
- Args:
185
- messages: The messages to extract request from
186
-
187
- Returns:
188
- RouterResult containing the selected agent, or None if no suitable agent found
189
- """
190
- if not self.initialized:
191
- await self.initialize()
192
-
193
- # Extract the request text from the last message
194
- request = messages[-1].all_text() if messages else ""
195
-
196
- # Determine which agent to route to
197
- routing_result = await self._route_request(request)
198
-
199
- if not routing_result:
200
- logger.warning("Could not determine appropriate agent for this request")
201
-
202
- return routing_result
137
+ llm_factory: type[AugmentedLLMProtocol] | Callable[..., AugmentedLLMProtocol],
138
+ model: str | None = None,
139
+ request_params: RequestParams | None = None,
140
+ **additional_kwargs,
141
+ ) -> AugmentedLLMProtocol:
142
+ return await super().attach_llm(
143
+ llm_factory, model, request_params, verb="Routing", **additional_kwargs
144
+ )
203
145
 
204
146
  async def generate(
205
147
  self,
@@ -216,32 +158,21 @@ class RouterAgent(BaseAgent):
216
158
  Returns:
217
159
  The response from the selected agent
218
160
  """
219
- routing_result = await self._get_routing_result(multipart_messages)
220
-
221
- if not routing_result:
222
- return PromptMessageMultipart(
223
- role="assistant",
224
- content=[
225
- TextContent(
226
- type="text", text="Could not determine appropriate agent for this request."
227
- )
228
- ],
229
- )
230
161
 
231
- # Get the selected agent
232
- selected_agent = routing_result.result
162
+ route, warn = await self._route_request(multipart_messages[-1])
233
163
 
234
- # Log the routing decision
235
- logger.info(
236
- f"Routing request to agent: {selected_agent.name} (confidence: {routing_result.confidence})"
237
- )
164
+ if not route:
165
+ return Prompt.assistant(warn or "No routing result or warning received")
166
+
167
+ # Get the selected agent
168
+ agent: Agent = self.agent_map[route.agent]
238
169
 
239
170
  # Dispatch the request to the selected agent
240
- return await selected_agent.generate(multipart_messages, request_params)
171
+ return await agent.generate(multipart_messages, request_params)
241
172
 
242
173
  async def structured(
243
174
  self,
244
- prompt: List[PromptMessageMultipart],
175
+ multipart_messages: List[PromptMessageMultipart],
245
176
  model: Type[ModelT],
246
177
  request_params: Optional[RequestParams] = None,
247
178
  ) -> Tuple[ModelT | None, PromptMessageMultipart]:
@@ -256,23 +187,22 @@ class RouterAgent(BaseAgent):
256
187
  Returns:
257
188
  The parsed response from the selected agent, or None if parsing fails
258
189
  """
259
- routing_result = await self._get_routing_result(prompt)
190
+ route, warn = await self._route_request(multipart_messages[-1])
260
191
 
261
- if not routing_result:
262
- return None, Prompt.assistant("No routing result")
192
+ if not route:
193
+ return None, Prompt.assistant(
194
+ warn or "No routing result or warning received (structured)"
195
+ )
263
196
 
264
197
  # Get the selected agent
265
- selected_agent = routing_result.result
266
-
267
- # Log the routing decision
268
- logger.info(
269
- f"Routing structured request to agent: {selected_agent.name} (confidence: {routing_result.confidence})"
270
- )
198
+ agent: Agent = self.agent_map[route.agent]
271
199
 
272
200
  # Dispatch the request to the selected agent
273
- return await selected_agent.structured(prompt, model, request_params)
201
+ return await agent.structured(multipart_messages, model, request_params)
274
202
 
275
- async def _route_request(self, request: str) -> Optional[RouterResult]:
203
+ async def _route_request(
204
+ self, message: PromptMessageMultipart
205
+ ) -> Tuple[RoutingResponse | None, str | None]:
276
206
  """
277
207
  Determine which agent to route the request to.
278
208
 
@@ -283,49 +213,53 @@ class RouterAgent(BaseAgent):
283
213
  RouterResult containing the selected agent, or None if no suitable agent was found
284
214
  """
285
215
  if not self.agents:
286
- logger.warning("No agents available for routing")
287
- return None
216
+ logger.error("No agents available for routing")
217
+ raise AgentConfigError("No agents available for routing - fatal error")
288
218
 
289
219
  # If only one agent is available, use it directly
290
220
  if len(self.agents) == 1:
291
- return RouterResult(
292
- result=self.agents[0], confidence="high", reasoning="Only one agent available"
293
- )
221
+ return RoutingResponse(
222
+ agent=self.agents[0].name, confidence="high", reasoning="Only one agent available"
223
+ ), None
294
224
 
295
225
  # Generate agent descriptions for the context
296
226
  agent_descriptions = []
297
- for i, agent in enumerate(self.agents, 1):
298
- description = agent.instruction if isinstance(agent.instruction, str) else ""
299
- agent_descriptions.append(f"{i}. Name: {agent.name} - {description}")
227
+ for agent in self.agents:
228
+ agent_card: AgentCard = await agent.agent_card()
229
+ agent_descriptions.append(
230
+ agent_card.model_dump_json(
231
+ include={"name", "description", "skills"}, exclude_none=True
232
+ )
233
+ )
300
234
 
301
- context = "\n\n".join(agent_descriptions)
235
+ context = ",\n".join(agent_descriptions)
302
236
 
303
237
  # Format the routing prompt
304
238
  routing_instruction = self.routing_instruction or DEFAULT_ROUTING_INSTRUCTION
305
- prompt_text = routing_instruction.format(context=context, request=request)
306
-
307
- # Create multipart message for the router
308
- prompt = PromptMessageMultipart(
309
- role="user", content=[TextContent(type="text", text=prompt_text)]
310
- )
239
+ routing_instruction = routing_instruction.format(context=context)
311
240
 
312
- # Get structured response from LLM
313
241
  assert self._llm
242
+ mutated = message.model_copy(deep=True)
243
+ mutated.add_text(routing_instruction)
314
244
  response, _ = await self._llm.structured(
315
- [prompt], RoutingResponse, self._default_request_params
245
+ [mutated],
246
+ RoutingResponse,
247
+ self._default_request_params,
316
248
  )
317
249
 
250
+ warn: str | None = None
318
251
  if not response:
319
- logger.warning("No routing response received from LLM")
320
- return None
252
+ warn = "No routing response received from LLM"
253
+ elif response.agent not in self.agent_map:
254
+ warn = f"A response was received, but the agent {response.agent} was not known to the Router"
321
255
 
322
- # Look up the agent by name
323
- selected_agent = self.agent_map.get(response.agent)
324
-
325
- if not selected_agent:
326
- logger.warning(f"Agent '{response.agent}' not found in available agents")
327
- return None
256
+ if warn:
257
+ logger.warning(warn)
258
+ return None, warn
259
+ else:
260
+ assert response
261
+ logger.info(
262
+ f"Routing structured request to agent: {response.agent or 'error'} (confidence: {response.confidence or ''})"
263
+ )
328
264
 
329
- return RouterResult(
330
- result=selected_agent, confidence=response.confidence, reasoning=response.reasoning
331
- )
265
+ return response, None