fast-agent-mcp 0.2.57__py3-none-any.whl → 0.3.0__py3-none-any.whl

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 (234) hide show
  1. fast_agent/__init__.py +127 -0
  2. fast_agent/agents/__init__.py +36 -0
  3. {mcp_agent/core → fast_agent/agents}/agent_types.py +2 -1
  4. fast_agent/agents/llm_agent.py +217 -0
  5. fast_agent/agents/llm_decorator.py +486 -0
  6. mcp_agent/agents/base_agent.py → fast_agent/agents/mcp_agent.py +377 -385
  7. fast_agent/agents/tool_agent.py +168 -0
  8. {mcp_agent → fast_agent}/agents/workflow/chain_agent.py +43 -33
  9. {mcp_agent → fast_agent}/agents/workflow/evaluator_optimizer.py +31 -35
  10. {mcp_agent → fast_agent}/agents/workflow/iterative_planner.py +56 -47
  11. {mcp_agent → fast_agent}/agents/workflow/orchestrator_models.py +4 -4
  12. {mcp_agent → fast_agent}/agents/workflow/parallel_agent.py +34 -41
  13. {mcp_agent → fast_agent}/agents/workflow/router_agent.py +54 -39
  14. {mcp_agent → fast_agent}/cli/__main__.py +5 -3
  15. {mcp_agent → fast_agent}/cli/commands/check_config.py +95 -66
  16. {mcp_agent → fast_agent}/cli/commands/go.py +20 -11
  17. {mcp_agent → fast_agent}/cli/commands/quickstart.py +4 -4
  18. {mcp_agent → fast_agent}/cli/commands/server_helpers.py +1 -1
  19. {mcp_agent → fast_agent}/cli/commands/setup.py +64 -134
  20. {mcp_agent → fast_agent}/cli/commands/url_parser.py +9 -8
  21. {mcp_agent → fast_agent}/cli/main.py +36 -16
  22. {mcp_agent → fast_agent}/cli/terminal.py +2 -2
  23. {mcp_agent → fast_agent}/config.py +13 -2
  24. fast_agent/constants.py +8 -0
  25. {mcp_agent → fast_agent}/context.py +24 -19
  26. {mcp_agent → fast_agent}/context_dependent.py +9 -5
  27. fast_agent/core/__init__.py +17 -0
  28. {mcp_agent → fast_agent}/core/agent_app.py +39 -36
  29. fast_agent/core/core_app.py +135 -0
  30. {mcp_agent → fast_agent}/core/direct_decorators.py +12 -26
  31. {mcp_agent → fast_agent}/core/direct_factory.py +95 -73
  32. {mcp_agent → fast_agent/core}/executor/executor.py +4 -5
  33. {mcp_agent → fast_agent}/core/fastagent.py +32 -32
  34. fast_agent/core/logging/__init__.py +5 -0
  35. {mcp_agent → fast_agent/core}/logging/events.py +3 -3
  36. {mcp_agent → fast_agent/core}/logging/json_serializer.py +1 -1
  37. {mcp_agent → fast_agent/core}/logging/listeners.py +85 -7
  38. {mcp_agent → fast_agent/core}/logging/logger.py +7 -7
  39. {mcp_agent → fast_agent/core}/logging/transport.py +10 -11
  40. fast_agent/core/prompt.py +9 -0
  41. {mcp_agent → fast_agent}/core/validation.py +4 -4
  42. fast_agent/event_progress.py +61 -0
  43. fast_agent/history/history_exporter.py +44 -0
  44. {mcp_agent → fast_agent}/human_input/__init__.py +9 -12
  45. {mcp_agent → fast_agent}/human_input/elicitation_handler.py +26 -8
  46. {mcp_agent → fast_agent}/human_input/elicitation_state.py +7 -7
  47. {mcp_agent → fast_agent}/human_input/simple_form.py +6 -4
  48. {mcp_agent → fast_agent}/human_input/types.py +1 -18
  49. fast_agent/interfaces.py +228 -0
  50. fast_agent/llm/__init__.py +9 -0
  51. mcp_agent/llm/augmented_llm.py → fast_agent/llm/fastagent_llm.py +128 -218
  52. fast_agent/llm/internal/passthrough.py +137 -0
  53. mcp_agent/llm/augmented_llm_playback.py → fast_agent/llm/internal/playback.py +29 -25
  54. mcp_agent/llm/augmented_llm_silent.py → fast_agent/llm/internal/silent.py +10 -17
  55. fast_agent/llm/internal/slow.py +38 -0
  56. {mcp_agent → fast_agent}/llm/memory.py +40 -30
  57. {mcp_agent → fast_agent}/llm/model_database.py +35 -2
  58. {mcp_agent → fast_agent}/llm/model_factory.py +103 -77
  59. fast_agent/llm/model_info.py +126 -0
  60. {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/anthropic_utils.py +7 -7
  61. fast_agent/llm/provider/anthropic/llm_anthropic.py +603 -0
  62. {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/multipart_converter_anthropic.py +79 -86
  63. fast_agent/llm/provider/bedrock/bedrock_utils.py +218 -0
  64. fast_agent/llm/provider/bedrock/llm_bedrock.py +2192 -0
  65. {mcp_agent/llm/providers → fast_agent/llm/provider/google}/google_converter.py +66 -14
  66. fast_agent/llm/provider/google/llm_google_native.py +431 -0
  67. mcp_agent/llm/providers/augmented_llm_aliyun.py → fast_agent/llm/provider/openai/llm_aliyun.py +6 -7
  68. mcp_agent/llm/providers/augmented_llm_azure.py → fast_agent/llm/provider/openai/llm_azure.py +4 -4
  69. mcp_agent/llm/providers/augmented_llm_deepseek.py → fast_agent/llm/provider/openai/llm_deepseek.py +10 -11
  70. mcp_agent/llm/providers/augmented_llm_generic.py → fast_agent/llm/provider/openai/llm_generic.py +4 -4
  71. mcp_agent/llm/providers/augmented_llm_google_oai.py → fast_agent/llm/provider/openai/llm_google_oai.py +4 -4
  72. mcp_agent/llm/providers/augmented_llm_groq.py → fast_agent/llm/provider/openai/llm_groq.py +14 -16
  73. mcp_agent/llm/providers/augmented_llm_openai.py → fast_agent/llm/provider/openai/llm_openai.py +133 -206
  74. mcp_agent/llm/providers/augmented_llm_openrouter.py → fast_agent/llm/provider/openai/llm_openrouter.py +6 -6
  75. mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py → fast_agent/llm/provider/openai/llm_tensorzero_openai.py +17 -16
  76. mcp_agent/llm/providers/augmented_llm_xai.py → fast_agent/llm/provider/openai/llm_xai.py +6 -6
  77. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/multipart_converter_openai.py +125 -63
  78. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_multipart.py +12 -12
  79. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_utils.py +18 -16
  80. {mcp_agent → fast_agent}/llm/provider_key_manager.py +2 -2
  81. {mcp_agent → fast_agent}/llm/provider_types.py +2 -0
  82. {mcp_agent → fast_agent}/llm/sampling_converter.py +15 -12
  83. {mcp_agent → fast_agent}/llm/usage_tracking.py +23 -5
  84. fast_agent/mcp/__init__.py +43 -0
  85. {mcp_agent → fast_agent}/mcp/elicitation_factory.py +3 -3
  86. {mcp_agent → fast_agent}/mcp/elicitation_handlers.py +19 -10
  87. {mcp_agent → fast_agent}/mcp/gen_client.py +3 -3
  88. fast_agent/mcp/helpers/__init__.py +36 -0
  89. fast_agent/mcp/helpers/content_helpers.py +183 -0
  90. {mcp_agent → fast_agent}/mcp/helpers/server_config_helpers.py +8 -8
  91. {mcp_agent → fast_agent}/mcp/hf_auth.py +25 -23
  92. fast_agent/mcp/interfaces.py +93 -0
  93. {mcp_agent → fast_agent}/mcp/logger_textio.py +4 -4
  94. {mcp_agent → fast_agent}/mcp/mcp_agent_client_session.py +49 -44
  95. {mcp_agent → fast_agent}/mcp/mcp_aggregator.py +66 -115
  96. {mcp_agent → fast_agent}/mcp/mcp_connection_manager.py +16 -23
  97. {mcp_agent/core → fast_agent/mcp}/mcp_content.py +23 -15
  98. {mcp_agent → fast_agent}/mcp/mime_utils.py +39 -0
  99. fast_agent/mcp/prompt.py +159 -0
  100. mcp_agent/mcp/prompt_message_multipart.py → fast_agent/mcp/prompt_message_extended.py +27 -20
  101. {mcp_agent → fast_agent}/mcp/prompt_render.py +21 -19
  102. {mcp_agent → fast_agent}/mcp/prompt_serialization.py +46 -46
  103. fast_agent/mcp/prompts/__main__.py +7 -0
  104. {mcp_agent → fast_agent}/mcp/prompts/prompt_helpers.py +31 -30
  105. {mcp_agent → fast_agent}/mcp/prompts/prompt_load.py +8 -8
  106. {mcp_agent → fast_agent}/mcp/prompts/prompt_server.py +11 -19
  107. {mcp_agent → fast_agent}/mcp/prompts/prompt_template.py +18 -18
  108. {mcp_agent → fast_agent}/mcp/resource_utils.py +1 -1
  109. {mcp_agent → fast_agent}/mcp/sampling.py +31 -26
  110. {mcp_agent/mcp_server → fast_agent/mcp/server}/__init__.py +1 -1
  111. {mcp_agent/mcp_server → fast_agent/mcp/server}/agent_server.py +5 -6
  112. fast_agent/mcp/ui_agent.py +48 -0
  113. fast_agent/mcp/ui_mixin.py +209 -0
  114. fast_agent/mcp_server_registry.py +90 -0
  115. {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis-campaign.py +5 -4
  116. {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis.py +1 -1
  117. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_forms_server.py +25 -3
  118. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/forms_demo.py +3 -3
  119. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character.py +2 -2
  120. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character_handler.py +1 -1
  121. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/tool_call.py +1 -1
  122. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_one.py +1 -1
  123. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_two.py +1 -1
  124. {mcp_agent → fast_agent}/resources/examples/researcher/researcher-eval.py +1 -1
  125. {mcp_agent → fast_agent}/resources/examples/researcher/researcher-imp.py +1 -1
  126. {mcp_agent → fast_agent}/resources/examples/researcher/researcher.py +1 -1
  127. {mcp_agent → fast_agent}/resources/examples/tensorzero/agent.py +2 -2
  128. {mcp_agent → fast_agent}/resources/examples/tensorzero/image_demo.py +3 -3
  129. {mcp_agent → fast_agent}/resources/examples/tensorzero/simple_agent.py +1 -1
  130. {mcp_agent → fast_agent}/resources/examples/workflows/chaining.py +1 -1
  131. {mcp_agent → fast_agent}/resources/examples/workflows/evaluator.py +3 -3
  132. {mcp_agent → fast_agent}/resources/examples/workflows/human_input.py +5 -3
  133. {mcp_agent → fast_agent}/resources/examples/workflows/orchestrator.py +1 -1
  134. {mcp_agent → fast_agent}/resources/examples/workflows/parallel.py +2 -2
  135. {mcp_agent → fast_agent}/resources/examples/workflows/router.py +5 -2
  136. fast_agent/resources/setup/.gitignore +24 -0
  137. fast_agent/resources/setup/agent.py +18 -0
  138. fast_agent/resources/setup/fastagent.config.yaml +44 -0
  139. fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
  140. fast_agent/tools/elicitation.py +369 -0
  141. fast_agent/types/__init__.py +32 -0
  142. fast_agent/types/llm_stop_reason.py +77 -0
  143. fast_agent/ui/__init__.py +38 -0
  144. fast_agent/ui/console_display.py +1005 -0
  145. {mcp_agent/human_input → fast_agent/ui}/elicitation_form.py +56 -39
  146. mcp_agent/human_input/elicitation_forms.py → fast_agent/ui/elicitation_style.py +1 -1
  147. {mcp_agent/core → fast_agent/ui}/enhanced_prompt.py +96 -25
  148. {mcp_agent/core → fast_agent/ui}/interactive_prompt.py +330 -125
  149. fast_agent/ui/mcp_ui_utils.py +224 -0
  150. {mcp_agent → fast_agent/ui}/progress_display.py +2 -2
  151. {mcp_agent/logging → fast_agent/ui}/rich_progress.py +4 -4
  152. {mcp_agent/core → fast_agent/ui}/usage_display.py +3 -8
  153. {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/METADATA +7 -7
  154. fast_agent_mcp-0.3.0.dist-info/RECORD +202 -0
  155. fast_agent_mcp-0.3.0.dist-info/entry_points.txt +5 -0
  156. fast_agent_mcp-0.2.57.dist-info/RECORD +0 -192
  157. fast_agent_mcp-0.2.57.dist-info/entry_points.txt +0 -6
  158. mcp_agent/__init__.py +0 -114
  159. mcp_agent/agents/agent.py +0 -92
  160. mcp_agent/agents/workflow/__init__.py +0 -1
  161. mcp_agent/agents/workflow/orchestrator_agent.py +0 -597
  162. mcp_agent/app.py +0 -175
  163. mcp_agent/core/__init__.py +0 -26
  164. mcp_agent/core/prompt.py +0 -191
  165. mcp_agent/event_progress.py +0 -134
  166. mcp_agent/human_input/handler.py +0 -81
  167. mcp_agent/llm/__init__.py +0 -2
  168. mcp_agent/llm/augmented_llm_passthrough.py +0 -232
  169. mcp_agent/llm/augmented_llm_slow.py +0 -53
  170. mcp_agent/llm/providers/__init__.py +0 -8
  171. mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -717
  172. mcp_agent/llm/providers/augmented_llm_bedrock.py +0 -1788
  173. mcp_agent/llm/providers/augmented_llm_google_native.py +0 -495
  174. mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -57
  175. mcp_agent/llm/providers/sampling_converter_openai.py +0 -26
  176. mcp_agent/llm/sampling_format_converter.py +0 -37
  177. mcp_agent/logging/__init__.py +0 -0
  178. mcp_agent/mcp/__init__.py +0 -50
  179. mcp_agent/mcp/helpers/__init__.py +0 -25
  180. mcp_agent/mcp/helpers/content_helpers.py +0 -187
  181. mcp_agent/mcp/interfaces.py +0 -266
  182. mcp_agent/mcp/prompts/__init__.py +0 -0
  183. mcp_agent/mcp/prompts/__main__.py +0 -10
  184. mcp_agent/mcp_server_registry.py +0 -343
  185. mcp_agent/tools/tool_definition.py +0 -14
  186. mcp_agent/ui/console_display.py +0 -790
  187. mcp_agent/ui/console_display_legacy.py +0 -401
  188. {mcp_agent → fast_agent}/agents/workflow/orchestrator_prompts.py +0 -0
  189. {mcp_agent/agents → fast_agent/cli}/__init__.py +0 -0
  190. {mcp_agent → fast_agent}/cli/constants.py +0 -0
  191. {mcp_agent → fast_agent}/core/error_handling.py +0 -0
  192. {mcp_agent → fast_agent}/core/exceptions.py +0 -0
  193. {mcp_agent/cli → fast_agent/core/executor}/__init__.py +0 -0
  194. {mcp_agent → fast_agent/core}/executor/task_registry.py +0 -0
  195. {mcp_agent → fast_agent/core}/executor/workflow_signal.py +0 -0
  196. {mcp_agent → fast_agent}/human_input/form_fields.py +0 -0
  197. {mcp_agent → fast_agent}/llm/prompt_utils.py +0 -0
  198. {mcp_agent/core → fast_agent/llm}/request_params.py +0 -0
  199. {mcp_agent → fast_agent}/mcp/common.py +0 -0
  200. {mcp_agent/executor → fast_agent/mcp/prompts}/__init__.py +0 -0
  201. {mcp_agent → fast_agent}/mcp/prompts/prompt_constants.py +0 -0
  202. {mcp_agent → fast_agent}/py.typed +0 -0
  203. {mcp_agent → fast_agent}/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  204. {mcp_agent → fast_agent}/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  205. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_account_server.py +0 -0
  206. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_game_server.py +0 -0
  207. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.config.yaml +0 -0
  208. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +0 -0
  209. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
  210. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
  211. {mcp_agent → fast_agent}/resources/examples/researcher/fastagent.config.yaml +0 -0
  212. {mcp_agent → fast_agent}/resources/examples/tensorzero/.env.sample +0 -0
  213. {mcp_agent → fast_agent}/resources/examples/tensorzero/Makefile +0 -0
  214. {mcp_agent → fast_agent}/resources/examples/tensorzero/README.md +0 -0
  215. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
  216. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/crab.png +0 -0
  217. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
  218. {mcp_agent → fast_agent}/resources/examples/tensorzero/docker-compose.yml +0 -0
  219. {mcp_agent → fast_agent}/resources/examples/tensorzero/fastagent.config.yaml +0 -0
  220. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/Dockerfile +0 -0
  221. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/entrypoint.sh +0 -0
  222. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/mcp_server.py +0 -0
  223. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/pyproject.toml +0 -0
  224. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_schema.json +0 -0
  225. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +0 -0
  226. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +0 -0
  227. {mcp_agent → fast_agent}/resources/examples/workflows/fastagent.config.yaml +0 -0
  228. {mcp_agent → fast_agent}/resources/examples/workflows/graded_report.md +0 -0
  229. {mcp_agent → fast_agent}/resources/examples/workflows/short_story.md +0 -0
  230. {mcp_agent → fast_agent}/resources/examples/workflows/short_story.txt +0 -0
  231. {mcp_agent → fast_agent/ui}/console.py +0 -0
  232. {mcp_agent/core → fast_agent/ui}/mermaid_utils.py +0 -0
  233. {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/WHEEL +0 -0
  234. {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -5,11 +5,12 @@ Iterative Planner Agent - works towards an objective using sub-agents
5
5
  import asyncio
6
6
  from typing import Any, Dict, List, Optional, Tuple, Type
7
7
 
8
+ from mcp import Tool
8
9
  from mcp.types import TextContent
9
10
 
10
- from mcp_agent.agents.agent import Agent
11
- from mcp_agent.agents.base_agent import BaseAgent
12
- from mcp_agent.agents.workflow.orchestrator_models import (
11
+ from fast_agent.agents.agent_types import AgentConfig, AgentType
12
+ from fast_agent.agents.llm_agent import LlmAgent
13
+ from fast_agent.agents.workflow.orchestrator_models import (
13
14
  Plan,
14
15
  PlanningStep,
15
16
  PlanResult,
@@ -18,13 +19,11 @@ from mcp_agent.agents.workflow.orchestrator_models import (
18
19
  format_plan_result,
19
20
  format_step_result_text,
20
21
  )
21
- from mcp_agent.core.agent_types import AgentConfig, AgentType
22
- from mcp_agent.core.exceptions import AgentConfigError
23
- from mcp_agent.core.prompt import Prompt
24
- from mcp_agent.core.request_params import RequestParams
25
- from mcp_agent.logging.logger import get_logger
26
- from mcp_agent.mcp.interfaces import ModelT
27
- from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
22
+ from fast_agent.core.exceptions import AgentConfigError
23
+ from fast_agent.core.logging.logger import get_logger
24
+ from fast_agent.core.prompt import Prompt
25
+ from fast_agent.interfaces import AgentProtocol, ModelT
26
+ from fast_agent.types import PromptMessageExtended, RequestParams
28
27
 
29
28
  logger = get_logger(__name__)
30
29
 
@@ -146,11 +145,11 @@ make sure to state clearly what was accomplished and what remains to be done.
146
145
 
147
146
 
148
147
  Complete the plan by providing an appropriate answer for the original objective. Provide a Mermaid diagram
149
- (in code fences) showing the plan steps and their relationships, if applicable.
148
+ (in code fences) showing the plan steps and their relationships, if applicable. Do not use parentheses in labels.
150
149
  """
151
150
 
152
151
 
153
- class IterativePlanner(BaseAgent):
152
+ class IterativePlanner(LlmAgent):
154
153
  """
155
154
  An agent that implements the orchestrator workflow pattern.
156
155
 
@@ -167,7 +166,7 @@ class IterativePlanner(BaseAgent):
167
166
  def __init__(
168
167
  self,
169
168
  config: AgentConfig,
170
- agents: List[Agent],
169
+ agents: List[AgentProtocol],
171
170
  plan_iterations: int = -1,
172
171
  context: Optional[Any] = None,
173
172
  **kwargs,
@@ -186,11 +185,13 @@ class IterativePlanner(BaseAgent):
186
185
  raise AgentConfigError("At least one worker agent must be provided")
187
186
 
188
187
  # Store agents by name for easier lookup
189
- self.agents: Dict[str, Agent] = {}
188
+ self.agents: Dict[str, AgentProtocol] = {}
190
189
  for agent in agents:
191
190
  agent_name = agent.name
192
191
  self.agents[agent_name] = agent
193
192
 
193
+ # Extract plan_type from kwargs before passing to parent
194
+ kwargs.pop("plan_type", "full")
194
195
  super().__init__(config, context=context, **kwargs)
195
196
 
196
197
  self.plan_iterations = plan_iterations
@@ -200,7 +201,7 @@ class IterativePlanner(BaseAgent):
200
201
  # Initialize all worker agents first if not already initialized
201
202
  for agent_name, agent in self.agents.items():
202
203
  if not getattr(agent, "initialized", False):
203
- self.logger.debug(f"Initializing agent: {agent_name}")
204
+ logger.debug(f"Initializing agent: {agent_name}")
204
205
  await agent.initialize()
205
206
 
206
207
  # Format agent information using agent cards with XML formatting
@@ -218,7 +219,6 @@ class IterativePlanner(BaseAgent):
218
219
 
219
220
  # Update the config instruction with the formatted system prompt
220
221
  self.instruction = system_prompt
221
-
222
222
  # Initialize the base agent with the updated system prompt
223
223
  await super().initialize()
224
224
 
@@ -233,44 +233,44 @@ class IterativePlanner(BaseAgent):
233
233
  try:
234
234
  await agent.shutdown()
235
235
  except Exception as e:
236
- self.logger.warning(f"Error shutting down agent {agent_name}: {str(e)}")
236
+ logger.warning(f"Error shutting down agent {agent_name}: {str(e)}")
237
237
 
238
- async def generate(
238
+ async def generate_impl(
239
239
  self,
240
- multipart_messages: List[PromptMessageMultipart],
241
- request_params: Optional[RequestParams] = None,
242
- ) -> PromptMessageMultipart:
240
+ messages: List[PromptMessageExtended],
241
+ request_params: RequestParams | None = None,
242
+ tools: List[Tool] | None = None,
243
+ ) -> PromptMessageExtended:
243
244
  """
244
245
  Execute an orchestrated plan to process the input.
245
246
 
246
247
  Args:
247
- multipart_messages: Messages to process
248
+ normalized_messages: Already normalized list of PromptMessageExtended
248
249
  request_params: Optional request parameters
249
250
 
250
251
  Returns:
251
252
  The final synthesized response from the orchestration
252
253
  """
253
254
  # Extract user request
254
- objective = multipart_messages[-1].all_text() if multipart_messages else ""
255
+ objective = messages[-1].all_text() if messages else ""
255
256
  plan_result = await self._execute_plan(objective, request_params)
256
-
257
257
  # Return the result
258
- return PromptMessageMultipart(
258
+ return PromptMessageExtended(
259
259
  role="assistant",
260
260
  content=[TextContent(type="text", text=plan_result.result or "No result available")],
261
261
  )
262
262
 
263
- async def structured(
263
+ async def structured_impl(
264
264
  self,
265
- multipart_messages: List[PromptMessageMultipart],
265
+ messages: List[PromptMessageExtended],
266
266
  model: Type[ModelT],
267
267
  request_params: Optional[RequestParams] = None,
268
- ) -> Tuple[ModelT | None, PromptMessageMultipart]:
268
+ ) -> Tuple[ModelT | None, PromptMessageExtended]:
269
269
  """
270
270
  Execute an orchestration plan and parse the result into a structured format.
271
271
 
272
272
  Args:
273
- prompt: List of messages to process
273
+ messages: List of messages to process
274
274
  model: Pydantic model to parse the response into
275
275
  request_params: Optional request parameters
276
276
 
@@ -278,18 +278,18 @@ class IterativePlanner(BaseAgent):
278
278
  The parsed final response, or None if parsing fails
279
279
  """
280
280
  # Generate orchestration result
281
- response = await self.generate(multipart_messages, request_params)
281
+ response = await self.generate_impl(messages, request_params)
282
282
 
283
283
  # Try to parse the response into the specified model
284
284
  try:
285
- result_text = response.last_text()
286
- prompt_message = PromptMessageMultipart(
285
+ result_text = response.last_text() or "<no text>"
286
+ prompt_message = PromptMessageExtended(
287
287
  role="user", content=[TextContent(type="text", text=result_text)]
288
288
  )
289
289
  assert self._llm
290
290
  return await self._llm.structured([prompt_message], model, request_params)
291
291
  except Exception as e:
292
- self.logger.warning(f"Failed to parse orchestration result: {str(e)}")
292
+ logger.warning(f"Failed to parse orchestration result: {str(e)}")
293
293
  return None, Prompt.assistant(f"Failed to parse orchestration result: {str(e)}")
294
294
 
295
295
  async def _execute_plan(
@@ -317,7 +317,7 @@ class IterativePlanner(BaseAgent):
317
317
 
318
318
  if None is next_step:
319
319
  terminate_plan = "Failed to generate plan, terminating early"
320
- self.logger.error("Failed to generate next step, terminating plan early")
320
+ logger.error("Failed to generate next step, terminating plan early")
321
321
  break
322
322
 
323
323
  assert next_step # lets keep the indenting manageable!
@@ -330,7 +330,7 @@ class IterativePlanner(BaseAgent):
330
330
  plan = Plan(steps=[next_step], is_complete=next_step.is_complete)
331
331
  invalid_agents = self._validate_agent_names(plan)
332
332
  if invalid_agents:
333
- self.logger.error(f"Plan contains invalid agent names: {', '.join(invalid_agents)}")
333
+ logger.error(f"Plan contains invalid agent names: {', '.join(invalid_agents)}")
334
334
  terminate_plan = (
335
335
  f"Invalid agent names found ({', '.join(invalid_agents)}), terminating plan"
336
336
  )
@@ -354,7 +354,9 @@ class IterativePlanner(BaseAgent):
354
354
  )
355
355
 
356
356
  # Generate final synthesis
357
- plan_result.result = await self._planner_generate_str(result_prompt, request_params)
357
+ final_message = await self._planner_generate_str(result_prompt, request_params)
358
+ plan_result.result = final_message.last_text() or "No final message generated"
359
+ await self.show_assistant_message(final_message)
358
360
  return plan_result
359
361
 
360
362
  async def _execute_step(self, step: Step, previous_result: PlanResult) -> Any:
@@ -369,7 +371,7 @@ class IterativePlanner(BaseAgent):
369
371
  Returns:
370
372
  Result of executing the step
371
373
  """
372
- from mcp_agent.agents.workflow.orchestrator_models import StepResult
374
+ from fast_agent.agents.workflow.orchestrator_models import StepResult
373
375
 
374
376
  # Initialize step result
375
377
  step_result = StepResult(step=step, task_results=[])
@@ -397,7 +399,7 @@ class IterativePlanner(BaseAgent):
397
399
  )
398
400
  result = await agent.generate(
399
401
  [
400
- PromptMessageMultipart(
402
+ PromptMessageExtended(
401
403
  role="user",
402
404
  content=[TextContent(type="text", text=task_description)],
403
405
  )
@@ -409,11 +411,11 @@ class IterativePlanner(BaseAgent):
409
411
  TaskWithResult(
410
412
  description=task_model["description"],
411
413
  agent=task_model["agent"],
412
- result=result.last_text(),
414
+ result=result.last_text() or "<missing response>",
413
415
  )
414
416
  )
415
417
  except Exception as e:
416
- self.logger.error(f"Error executing task: {str(e)}")
418
+ logger.error(f"Error executing task: {str(e)}")
417
419
  task_model = task.model_dump()
418
420
  results.append(
419
421
  TaskWithResult(
@@ -484,16 +486,24 @@ class IterativePlanner(BaseAgent):
484
486
  iterations_info=iterations_info,
485
487
  )
486
488
 
489
+ request_params = self._merge_request_params(
490
+ request_params, RequestParams(systemPrompt=self.instruction)
491
+ )
492
+
487
493
  # Get structured response from LLM
488
494
  try:
489
- plan_msg = PromptMessageMultipart(
495
+ plan_msg = PromptMessageExtended(
490
496
  role="user", content=[TextContent(type="text", text=prompt)]
491
497
  )
492
498
  assert self._llm
493
- next_step, _ = await self._llm.structured([plan_msg], PlanningStep, request_params)
499
+ self.show_user_message(plan_msg)
500
+ next_step, raw_response = await self._llm.structured(
501
+ [plan_msg], PlanningStep, request_params
502
+ )
503
+ await self.show_assistant_message(raw_response)
494
504
  return next_step
495
505
  except Exception as e:
496
- self.logger.error(f"Failed to parse next step: {str(e)}")
506
+ logger.error(f"Failed to parse next step: {str(e)}")
497
507
  return None
498
508
 
499
509
  def _validate_agent_names(self, plan: Plan) -> List[str]:
@@ -552,7 +562,7 @@ class IterativePlanner(BaseAgent):
552
562
 
553
563
  async def _planner_generate_str(
554
564
  self, message: str, request_params: RequestParams | None
555
- ) -> str:
565
+ ) -> PromptMessageExtended:
556
566
  """
557
567
  Generate string response from the orchestrator's own LLM.
558
568
 
@@ -564,9 +574,8 @@ class IterativePlanner(BaseAgent):
564
574
  String response from the LLM
565
575
  """
566
576
  # Create prompt message
567
- prompt = PromptMessageMultipart(
577
+ prompt = PromptMessageExtended(
568
578
  role="user", content=[TextContent(type="text", text=message)]
569
579
  )
570
580
  assert self._llm, "LLM must be initialized before generating text"
571
- response = await self._llm.generate([prompt], request_params)
572
- return response.last_text()
581
+ return await self._llm.generate([prompt], request_params)
@@ -2,7 +2,7 @@ from typing import List
2
2
 
3
3
  from pydantic import BaseModel, ConfigDict, Field
4
4
 
5
- from mcp_agent.agents.workflow.orchestrator_prompts import (
5
+ from fast_agent.agents.workflow.orchestrator_prompts import (
6
6
  PLAN_RESULT_TEMPLATE,
7
7
  STEP_RESULT_TEMPLATE,
8
8
  TASK_RESULT_TEMPLATE,
@@ -152,7 +152,7 @@ def format_plan_result_text(plan_result: PlanResult) -> str:
152
152
 
153
153
  def format_task_result_xml(task_result: TaskWithResult) -> str:
154
154
  """Format a task result with XML tags for better semantic understanding"""
155
- from mcp_agent.llm.prompt_utils import format_fastagent_tag
155
+ from fast_agent.llm.prompt_utils import format_fastagent_tag
156
156
 
157
157
  return format_fastagent_tag(
158
158
  "task-result",
@@ -168,7 +168,7 @@ def format_task_result_xml(task_result: TaskWithResult) -> str:
168
168
 
169
169
  def format_step_result_xml(step_result: StepResult) -> str:
170
170
  """Format a step result with XML tags for better semantic understanding"""
171
- from mcp_agent.llm.prompt_utils import format_fastagent_tag
171
+ from fast_agent.llm.prompt_utils import format_fastagent_tag
172
172
 
173
173
  # Format each task result with XML
174
174
  task_results = []
@@ -190,7 +190,7 @@ def format_step_result_xml(step_result: StepResult) -> str:
190
190
 
191
191
  def format_plan_result(plan_result: PlanResult) -> str:
192
192
  """Format the full plan execution state with XML for better semantic understanding"""
193
- from mcp_agent.llm.prompt_utils import format_fastagent_tag
193
+ from fast_agent.llm.prompt_utils import format_fastagent_tag
194
194
 
195
195
  # Format objective
196
196
  objective_tag = format_fastagent_tag("objective", plan_result.objective)
@@ -1,18 +1,20 @@
1
1
  import asyncio
2
2
  from typing import Any, List, Optional, Tuple
3
3
 
4
+ from mcp import Tool
4
5
  from mcp.types import TextContent
5
6
  from opentelemetry import trace
6
7
 
7
- from mcp_agent.agents.agent import Agent
8
- from mcp_agent.agents.base_agent import BaseAgent
9
- from mcp_agent.core.agent_types import AgentConfig, AgentType
10
- from mcp_agent.core.request_params import RequestParams
11
- from mcp_agent.mcp.interfaces import ModelT
12
- from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
8
+ from fast_agent.agents.agent_types import AgentConfig, AgentType
9
+ from fast_agent.agents.llm_agent import LlmAgent
10
+ from fast_agent.core.logging.logger import get_logger
11
+ from fast_agent.interfaces import AgentProtocol, ModelT
12
+ from fast_agent.types import PromptMessageExtended, RequestParams
13
13
 
14
+ logger = get_logger(__name__)
14
15
 
15
- class ParallelAgent(BaseAgent):
16
+
17
+ class ParallelAgent(LlmAgent):
16
18
  """
17
19
  LLMs can sometimes work simultaneously on a task (fan-out)
18
20
  and have their outputs aggregated programmatically (fan-in).
@@ -28,8 +30,8 @@ class ParallelAgent(BaseAgent):
28
30
  def __init__(
29
31
  self,
30
32
  config: AgentConfig,
31
- fan_in_agent: Agent,
32
- fan_out_agents: List[Agent],
33
+ fan_in_agent: AgentProtocol,
34
+ fan_out_agents: List[AgentProtocol],
33
35
  include_request: bool = True,
34
36
  **kwargs,
35
37
  ) -> None:
@@ -48,16 +50,17 @@ class ParallelAgent(BaseAgent):
48
50
  self.fan_out_agents = fan_out_agents
49
51
  self.include_request = include_request
50
52
 
51
- async def generate(
53
+ async def generate_impl(
52
54
  self,
53
- multipart_messages: List[PromptMessageMultipart],
55
+ messages: List[PromptMessageExtended],
54
56
  request_params: Optional[RequestParams] = None,
55
- ) -> PromptMessageMultipart:
57
+ tools: List[Tool] | None = None,
58
+ ) -> PromptMessageExtended:
56
59
  """
57
60
  Execute fan-out agents in parallel and aggregate their results with the fan-in agent.
58
61
 
59
62
  Args:
60
- multipart_messages: List of messages to send to the fan-out agents
63
+ normalized_messages: Already normalized list of PromptMessageExtended
61
64
  request_params: Optional parameters to configure the request
62
65
 
63
66
  Returns:
@@ -65,19 +68,14 @@ class ParallelAgent(BaseAgent):
65
68
  """
66
69
 
67
70
  tracer = trace.get_tracer(__name__)
68
- with tracer.start_as_current_span(f"Parallel: '{self.name}' generate"):
71
+ with tracer.start_as_current_span(f"Parallel: '{self._name}' generate"):
69
72
  # Execute all fan-out agents in parallel
70
- responses: List[PromptMessageMultipart] = await asyncio.gather(
71
- *[
72
- agent.generate(multipart_messages, request_params)
73
- for agent in self.fan_out_agents
74
- ]
73
+ responses: List[PromptMessageExtended] = await asyncio.gather(
74
+ *[agent.generate(messages, request_params) for agent in self.fan_out_agents]
75
75
  )
76
76
 
77
77
  # Extract the received message from the input
78
- received_message: Optional[str] = (
79
- multipart_messages[-1].all_text() if multipart_messages else None
80
- )
78
+ received_message: Optional[str] = messages[-1].all_text() if messages else None
81
79
 
82
80
  # Convert responses to strings for aggregation
83
81
  string_responses = []
@@ -88,7 +86,7 @@ class ParallelAgent(BaseAgent):
88
86
  aggregated_prompt = self._format_responses(string_responses, received_message)
89
87
 
90
88
  # Create a new multipart message with the formatted responses
91
- formatted_prompt = PromptMessageMultipart(
89
+ formatted_prompt = PromptMessageExtended(
92
90
  role="user", content=[TextContent(type="text", text=aggregated_prompt)]
93
91
  )
94
92
 
@@ -121,19 +119,19 @@ class ParallelAgent(BaseAgent):
121
119
  )
122
120
  return "\n\n".join(formatted)
123
121
 
124
- async def structured(
122
+ async def structured_impl(
125
123
  self,
126
- multipart_messages: List[PromptMessageMultipart],
124
+ messages: List[PromptMessageExtended],
127
125
  model: type[ModelT],
128
126
  request_params: Optional[RequestParams] = None,
129
- ) -> Tuple[ModelT | None, PromptMessageMultipart]:
127
+ ) -> Tuple[ModelT | None, PromptMessageExtended]:
130
128
  """
131
129
  Apply the prompt and return the result as a Pydantic model.
132
130
 
133
131
  This implementation delegates to the fan-in agent's structured method.
134
132
 
135
133
  Args:
136
- prompt: List of PromptMessageMultipart objects
134
+ messages: List of PromptMessageExtended objects
137
135
  model: The Pydantic model class to parse the result into
138
136
  request_params: Optional parameters to configure the LLM request
139
137
 
@@ -142,19 +140,14 @@ class ParallelAgent(BaseAgent):
142
140
  """
143
141
 
144
142
  tracer = trace.get_tracer(__name__)
145
- with tracer.start_as_current_span(f"Parallel: '{self.name}' generate"):
143
+ with tracer.start_as_current_span(f"Parallel: '{self._name}' generate"):
146
144
  # Generate parallel responses first
147
- responses: List[PromptMessageMultipart] = await asyncio.gather(
148
- *[
149
- agent.generate(multipart_messages, request_params)
150
- for agent in self.fan_out_agents
151
- ]
145
+ responses: List[PromptMessageExtended] = await asyncio.gather(
146
+ *[agent.generate(messages, request_params) for agent in self.fan_out_agents]
152
147
  )
153
148
 
154
149
  # Extract the received message
155
- received_message: Optional[str] = (
156
- multipart_messages[-1].all_text() if multipart_messages else None
157
- )
150
+ received_message: Optional[str] = messages[-1].all_text() if messages else None
158
151
 
159
152
  # Convert responses to strings
160
153
  string_responses = [response.all_text() for response in responses]
@@ -163,7 +156,7 @@ class ParallelAgent(BaseAgent):
163
156
  aggregated_prompt = self._format_responses(string_responses, received_message)
164
157
 
165
158
  # Create a multipart message
166
- formatted_prompt = PromptMessageMultipart(
159
+ formatted_prompt = PromptMessageExtended(
167
160
  role="user", content=[TextContent(type="text", text=aggregated_prompt)]
168
161
  )
169
162
 
@@ -177,11 +170,11 @@ class ParallelAgent(BaseAgent):
177
170
  await super().initialize()
178
171
 
179
172
  # Initialize fan-in and fan-out agents if not already initialized
180
- if not getattr(self.fan_in_agent, "initialized", False):
173
+ if not self.fan_in_agent.initialized:
181
174
  await self.fan_in_agent.initialize()
182
175
 
183
176
  for agent in self.fan_out_agents:
184
- if not getattr(agent, "initialized", False):
177
+ if not agent.initialized:
185
178
  await agent.initialize()
186
179
 
187
180
  async def shutdown(self) -> None:
@@ -194,10 +187,10 @@ class ParallelAgent(BaseAgent):
194
187
  try:
195
188
  await self.fan_in_agent.shutdown()
196
189
  except Exception as e:
197
- self.logger.warning(f"Error shutting down fan-in agent: {str(e)}")
190
+ logger.warning(f"Error shutting down fan-in agent: {str(e)}")
198
191
 
199
192
  for agent in self.fan_out_agents:
200
193
  try:
201
194
  await agent.shutdown()
202
195
  except Exception as e:
203
- self.logger.warning(f"Error shutting down fan-out agent {agent.name}: {str(e)}")
196
+ logger.warning(f"Error shutting down fan-out agent {agent.name}: {str(e)}")