fast-agent-mcp 0.1.12__py3-none-any.whl → 0.2.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.
Files changed (169) hide show
  1. {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
  2. fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
  3. mcp_agent/__init__.py +75 -0
  4. mcp_agent/agents/agent.py +61 -415
  5. mcp_agent/agents/base_agent.py +522 -0
  6. mcp_agent/agents/workflow/__init__.py +1 -0
  7. mcp_agent/agents/workflow/chain_agent.py +173 -0
  8. mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
  9. mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
  10. mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +11 -21
  11. mcp_agent/agents/workflow/parallel_agent.py +182 -0
  12. mcp_agent/agents/workflow/router_agent.py +307 -0
  13. mcp_agent/app.py +15 -19
  14. mcp_agent/cli/commands/bootstrap.py +19 -38
  15. mcp_agent/cli/commands/config.py +4 -4
  16. mcp_agent/cli/commands/setup.py +7 -14
  17. mcp_agent/cli/main.py +7 -10
  18. mcp_agent/cli/terminal.py +3 -3
  19. mcp_agent/config.py +25 -40
  20. mcp_agent/context.py +12 -21
  21. mcp_agent/context_dependent.py +3 -5
  22. mcp_agent/core/agent_types.py +10 -7
  23. mcp_agent/core/direct_agent_app.py +179 -0
  24. mcp_agent/core/direct_decorators.py +443 -0
  25. mcp_agent/core/direct_factory.py +476 -0
  26. mcp_agent/core/enhanced_prompt.py +23 -55
  27. mcp_agent/core/exceptions.py +8 -8
  28. mcp_agent/core/fastagent.py +145 -371
  29. mcp_agent/core/interactive_prompt.py +424 -0
  30. mcp_agent/core/mcp_content.py +17 -17
  31. mcp_agent/core/prompt.py +6 -9
  32. mcp_agent/core/request_params.py +6 -3
  33. mcp_agent/core/validation.py +92 -18
  34. mcp_agent/executor/decorator_registry.py +9 -17
  35. mcp_agent/executor/executor.py +8 -17
  36. mcp_agent/executor/task_registry.py +2 -4
  37. mcp_agent/executor/temporal.py +19 -41
  38. mcp_agent/executor/workflow.py +3 -5
  39. mcp_agent/executor/workflow_signal.py +15 -21
  40. mcp_agent/human_input/handler.py +4 -7
  41. mcp_agent/human_input/types.py +2 -3
  42. mcp_agent/llm/__init__.py +2 -0
  43. mcp_agent/llm/augmented_llm.py +450 -0
  44. mcp_agent/llm/augmented_llm_passthrough.py +162 -0
  45. mcp_agent/llm/augmented_llm_playback.py +83 -0
  46. mcp_agent/llm/memory.py +103 -0
  47. mcp_agent/{workflows/llm → llm}/model_factory.py +22 -16
  48. mcp_agent/{workflows/llm → llm}/prompt_utils.py +1 -3
  49. mcp_agent/llm/providers/__init__.py +8 -0
  50. mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +8 -25
  51. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +56 -194
  52. mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
  53. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +99 -190
  54. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +72 -71
  55. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +65 -71
  56. mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +16 -44
  57. mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +4 -4
  58. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +9 -11
  59. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +8 -12
  60. mcp_agent/{workflows/llm → llm}/sampling_converter.py +3 -31
  61. mcp_agent/llm/sampling_format_converter.py +37 -0
  62. mcp_agent/logging/events.py +1 -5
  63. mcp_agent/logging/json_serializer.py +7 -6
  64. mcp_agent/logging/listeners.py +20 -23
  65. mcp_agent/logging/logger.py +17 -19
  66. mcp_agent/logging/rich_progress.py +10 -8
  67. mcp_agent/logging/tracing.py +4 -6
  68. mcp_agent/logging/transport.py +22 -22
  69. mcp_agent/mcp/gen_client.py +1 -3
  70. mcp_agent/mcp/interfaces.py +117 -110
  71. mcp_agent/mcp/logger_textio.py +97 -0
  72. mcp_agent/mcp/mcp_agent_client_session.py +7 -7
  73. mcp_agent/mcp/mcp_agent_server.py +8 -8
  74. mcp_agent/mcp/mcp_aggregator.py +102 -143
  75. mcp_agent/mcp/mcp_connection_manager.py +20 -27
  76. mcp_agent/mcp/prompt_message_multipart.py +68 -16
  77. mcp_agent/mcp/prompt_render.py +77 -0
  78. mcp_agent/mcp/prompt_serialization.py +30 -48
  79. mcp_agent/mcp/prompts/prompt_constants.py +18 -0
  80. mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
  81. mcp_agent/mcp/prompts/prompt_load.py +109 -0
  82. mcp_agent/mcp/prompts/prompt_server.py +155 -195
  83. mcp_agent/mcp/prompts/prompt_template.py +35 -66
  84. mcp_agent/mcp/resource_utils.py +7 -14
  85. mcp_agent/mcp/sampling.py +17 -17
  86. mcp_agent/mcp_server/agent_server.py +13 -17
  87. mcp_agent/mcp_server_registry.py +13 -22
  88. mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +3 -2
  89. mcp_agent/resources/examples/in_dev/slides.py +110 -0
  90. mcp_agent/resources/examples/internal/agent.py +6 -3
  91. mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
  92. mcp_agent/resources/examples/internal/job.py +2 -1
  93. mcp_agent/resources/examples/internal/prompt_category.py +1 -1
  94. mcp_agent/resources/examples/internal/prompt_sizing.py +3 -5
  95. mcp_agent/resources/examples/internal/sizer.py +2 -1
  96. mcp_agent/resources/examples/internal/social.py +2 -1
  97. mcp_agent/resources/examples/prompting/agent.py +2 -1
  98. mcp_agent/resources/examples/prompting/image_server.py +4 -8
  99. mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
  100. mcp_agent/ui/console_display.py +16 -20
  101. fast_agent_mcp-0.1.12.dist-info/RECORD +0 -161
  102. mcp_agent/core/agent_app.py +0 -646
  103. mcp_agent/core/agent_utils.py +0 -71
  104. mcp_agent/core/decorators.py +0 -455
  105. mcp_agent/core/factory.py +0 -463
  106. mcp_agent/core/proxies.py +0 -269
  107. mcp_agent/core/types.py +0 -24
  108. mcp_agent/eval/__init__.py +0 -0
  109. mcp_agent/mcp/stdio.py +0 -111
  110. mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
  111. mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
  112. mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
  113. mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
  114. mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
  115. mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
  116. mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
  117. mcp_agent/resources/examples/researcher/researcher-imp.py +0 -190
  118. mcp_agent/resources/examples/researcher/researcher.py +0 -38
  119. mcp_agent/resources/examples/workflows/chaining.py +0 -44
  120. mcp_agent/resources/examples/workflows/evaluator.py +0 -78
  121. mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
  122. mcp_agent/resources/examples/workflows/human_input.py +0 -25
  123. mcp_agent/resources/examples/workflows/orchestrator.py +0 -73
  124. mcp_agent/resources/examples/workflows/parallel.py +0 -78
  125. mcp_agent/resources/examples/workflows/router.py +0 -53
  126. mcp_agent/resources/examples/workflows/sse.py +0 -23
  127. mcp_agent/telemetry/__init__.py +0 -0
  128. mcp_agent/telemetry/usage_tracking.py +0 -18
  129. mcp_agent/workflows/__init__.py +0 -0
  130. mcp_agent/workflows/embedding/__init__.py +0 -0
  131. mcp_agent/workflows/embedding/embedding_base.py +0 -61
  132. mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
  133. mcp_agent/workflows/embedding/embedding_openai.py +0 -46
  134. mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
  135. mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -481
  136. mcp_agent/workflows/intent_classifier/__init__.py +0 -0
  137. mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -120
  138. mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -134
  139. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -45
  140. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -45
  141. mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -161
  142. mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
  143. mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -60
  144. mcp_agent/workflows/llm/__init__.py +0 -0
  145. mcp_agent/workflows/llm/augmented_llm.py +0 -753
  146. mcp_agent/workflows/llm/augmented_llm_passthrough.py +0 -241
  147. mcp_agent/workflows/llm/augmented_llm_playback.py +0 -109
  148. mcp_agent/workflows/llm/providers/__init__.py +0 -8
  149. mcp_agent/workflows/llm/sampling_format_converter.py +0 -22
  150. mcp_agent/workflows/orchestrator/__init__.py +0 -0
  151. mcp_agent/workflows/orchestrator/orchestrator.py +0 -578
  152. mcp_agent/workflows/parallel/__init__.py +0 -0
  153. mcp_agent/workflows/parallel/fan_in.py +0 -350
  154. mcp_agent/workflows/parallel/fan_out.py +0 -187
  155. mcp_agent/workflows/parallel/parallel_llm.py +0 -166
  156. mcp_agent/workflows/router/__init__.py +0 -0
  157. mcp_agent/workflows/router/router_base.py +0 -368
  158. mcp_agent/workflows/router/router_embedding.py +0 -240
  159. mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
  160. mcp_agent/workflows/router/router_embedding_openai.py +0 -59
  161. mcp_agent/workflows/router/router_llm.py +0 -320
  162. mcp_agent/workflows/swarm/__init__.py +0 -0
  163. mcp_agent/workflows/swarm/swarm.py +0 -320
  164. mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
  165. mcp_agent/workflows/swarm/swarm_openai.py +0 -41
  166. {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
  167. {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
  168. {fast_agent_mcp-0.1.12.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
  169. /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
@@ -0,0 +1,179 @@
1
+ """
2
+ Direct AgentApp implementation for interacting with agents without proxies.
3
+ """
4
+
5
+ from typing import Dict, Optional, Union
6
+
7
+ from mcp_agent.agents.agent import Agent
8
+ from mcp_agent.core.interactive_prompt import InteractivePrompt
9
+ from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
10
+
11
+
12
+ class DirectAgentApp:
13
+ """
14
+ Container for active agents that provides a simple API for interacting with them.
15
+ This implementation works directly with Agent instances without proxies.
16
+
17
+ The DirectAgentApp provides both attribute-style access (app.agent_name)
18
+ and dictionary-style access (app["agent_name"]) to agents.
19
+
20
+ It also implements the AgentProtocol interface, automatically forwarding
21
+ calls to the default agent (the first agent in the container).
22
+ """
23
+
24
+ def __init__(self, agents: Dict[str, Agent]) -> None:
25
+ """
26
+ Initialize the DirectAgentApp.
27
+
28
+ Args:
29
+ agents: Dictionary of agent instances keyed by name
30
+ """
31
+ self._agents = agents
32
+
33
+ def __getitem__(self, key: str) -> Agent:
34
+ """Allow access to agents using dictionary syntax."""
35
+ if key not in self._agents:
36
+ raise KeyError(f"Agent '{key}' not found")
37
+ return self._agents[key]
38
+
39
+ def __getattr__(self, name: str) -> Agent:
40
+ """Allow access to agents using attribute syntax."""
41
+ if name in self._agents:
42
+ return self._agents[name]
43
+ raise AttributeError(f"Agent '{name}' not found")
44
+
45
+ async def __call__(
46
+ self,
47
+ message: Union[str, PromptMessageMultipart] | None = None,
48
+ agent_name: str | None = None,
49
+ default_prompt: str = "",
50
+ ) -> str:
51
+ """
52
+ Make the object callable to send messages or start interactive prompt.
53
+ This mirrors the FastAgent implementation that allowed agent("message").
54
+
55
+ Args:
56
+ message: The message to send
57
+ agent_name: Optional name of the agent to send to (defaults to first agent)
58
+ default: Default message to use in interactive prompt mode
59
+
60
+ Returns:
61
+ The agent's response as a string or the result of the interactive session
62
+ """
63
+ if message:
64
+ return await self._agent(agent_name).send(message)
65
+
66
+ return await self._agent(agent_name).prompt(default_prompt=default_prompt)
67
+
68
+ async def send(self, message: str, agent_name: Optional[str] = None) -> str:
69
+ """
70
+ Send a message to the specified agent (or to all agents).
71
+
72
+ Args:
73
+ message: The message to send
74
+ agent_name: Optional name of the agent to send to
75
+
76
+ Returns:
77
+ The agent's response as a string
78
+ """
79
+ return await self._agent(agent_name).send(message)
80
+
81
+ def _agent(self, agent_name: str | None) -> Agent:
82
+ if agent_name:
83
+ if agent_name not in self._agents:
84
+ raise ValueError(f"Agent '{agent_name}' not found")
85
+ return self._agents[agent_name]
86
+
87
+ return next(iter(self._agents.values()))
88
+
89
+ async def apply_prompt(
90
+ self,
91
+ prompt_name: str,
92
+ arguments: Dict[str, str] | None = None,
93
+ agent_name: str | None = None,
94
+ ) -> str:
95
+ """
96
+ Apply a prompt template to an agent (default agent if not specified).
97
+
98
+ Args:
99
+ prompt_name: Name of the prompt template to apply
100
+ agent_name: Name of the agent to send to
101
+ arguments: Optional arguments for the prompt template
102
+
103
+ Returns:
104
+ The agent's response as a string
105
+ """
106
+ return await self._agent(agent_name).apply_prompt(prompt_name, arguments)
107
+
108
+ async def list_prompts(self, agent_name: str | None = None):
109
+ """
110
+ List available prompts for an agent.
111
+
112
+ Args:
113
+ agent_name: Name of the agent to list prompts for
114
+
115
+ Returns:
116
+ Dictionary mapping server names to lists of available prompts
117
+ """
118
+ return await self._agent(agent_name).list_prompts()
119
+
120
+ async def with_resource(self, user_prompt: str, server_name: str, resource_name: str) -> str:
121
+ return await self._agent(None).with_resource(
122
+ prompt_content=user_prompt, server_name=server_name, resource_name=resource_name
123
+ )
124
+
125
+ async def prompt(self, agent_name: Optional[str] = None, default_prompt: str = "") -> str:
126
+ """
127
+ Interactive prompt for sending messages with advanced features.
128
+
129
+ Args:
130
+ agent_name: Optional target agent name (uses default if not specified)
131
+ default: Default message to use when user presses enter
132
+
133
+ Returns:
134
+ The result of the interactive session
135
+ """
136
+
137
+ # Get the default agent name if none specified
138
+ if agent_name:
139
+ # Validate that this agent exists
140
+ if agent_name not in self._agents:
141
+ raise ValueError(f"Agent '{agent_name}' not found")
142
+ target_name = agent_name
143
+ else:
144
+ # Use the first agent's name as default
145
+ target_name = next(iter(self._agents.keys()))
146
+
147
+ # Don't delegate to the agent's own prompt method - use our implementation
148
+ # The agent's prompt method doesn't fully support switching between agents
149
+
150
+ # Create agent_types dictionary mapping agent names to their types
151
+ agent_types = {}
152
+ for name, agent in self._agents.items():
153
+ # Determine agent type if possible
154
+ agent_type = "Agent" # Default type
155
+
156
+ # Try to get the type from the agent directly
157
+ if hasattr(agent, "agent_type"):
158
+ agent_type = agent.agent_type
159
+ elif hasattr(agent, "config") and hasattr(agent.config, "agent_type"):
160
+ agent_type = agent.config.agent_type
161
+
162
+ agent_types[name] = agent_type
163
+
164
+ # Create the interactive prompt
165
+ prompt = InteractivePrompt(agent_types=agent_types)
166
+
167
+ # Define the wrapper for send function
168
+ async def send_wrapper(message, agent_name):
169
+ return await self.send(message, agent_name)
170
+
171
+ # Start the prompt loop with the agent name (not the agent object)
172
+ return await prompt.prompt_loop(
173
+ send_func=send_wrapper,
174
+ default_agent=target_name, # Pass the agent name, not the agent object
175
+ available_agents=list(self._agents.keys()),
176
+ apply_prompt_func=self.apply_prompt,
177
+ list_prompts_func=self.list_prompts,
178
+ default=default_prompt,
179
+ )
@@ -0,0 +1,443 @@
1
+ """
2
+ Type-safe decorators for DirectFastAgent applications.
3
+ These decorators provide type-safe function signatures and IDE support
4
+ for creating agents in the DirectFastAgent framework.
5
+ """
6
+
7
+ import inspect
8
+ from functools import wraps
9
+ from typing import (
10
+ Awaitable,
11
+ Callable,
12
+ List,
13
+ Literal,
14
+ Optional,
15
+ ParamSpec,
16
+ Protocol,
17
+ TypeVar,
18
+ Union,
19
+ cast,
20
+ )
21
+
22
+ from mcp_agent.agents.agent import AgentConfig
23
+ from mcp_agent.core.agent_types import AgentType
24
+ from mcp_agent.core.request_params import RequestParams
25
+
26
+ # Type variables for the decorated function
27
+ P = ParamSpec("P") # Parameters
28
+ R = TypeVar("R") # Return type
29
+
30
+ # Type for agent functions - can be either async or sync
31
+ AgentCallable = Callable[P, Union[Awaitable[R], R]]
32
+
33
+
34
+ # Protocol for decorated agent functions
35
+ class DecoratedAgentProtocol(Protocol[P, R]):
36
+ """Protocol defining the interface of a decorated agent function."""
37
+
38
+ _agent_type: AgentType
39
+ _agent_config: AgentConfig
40
+
41
+ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Union[Awaitable[R], R]: ...
42
+
43
+
44
+ # Protocol for orchestrator functions
45
+ class DecoratedOrchestratorProtocol(DecoratedAgentProtocol[P, R], Protocol):
46
+ """Protocol for decorated orchestrator functions with additional metadata."""
47
+
48
+ _child_agents: List[str]
49
+ _plan_type: Literal["full", "iterative"]
50
+
51
+
52
+ # Protocol for router functions
53
+ class DecoratedRouterProtocol(DecoratedAgentProtocol[P, R], Protocol):
54
+ """Protocol for decorated router functions with additional metadata."""
55
+
56
+ _router_agents: List[str]
57
+
58
+
59
+ # Protocol for chain functions
60
+ class DecoratedChainProtocol(DecoratedAgentProtocol[P, R], Protocol):
61
+ """Protocol for decorated chain functions with additional metadata."""
62
+
63
+ _chain_agents: List[str]
64
+
65
+
66
+ # Protocol for parallel functions
67
+ class DecoratedParallelProtocol(DecoratedAgentProtocol[P, R], Protocol):
68
+ """Protocol for decorated parallel functions with additional metadata."""
69
+
70
+ _fan_out: List[str]
71
+ _fan_in: str
72
+
73
+
74
+ # Protocol for evaluator-optimizer functions
75
+ class DecoratedEvaluatorOptimizerProtocol(DecoratedAgentProtocol[P, R], Protocol):
76
+ """Protocol for decorated evaluator-optimizer functions with additional metadata."""
77
+
78
+ _generator: str
79
+ _evaluator: str
80
+
81
+
82
+ def _decorator_impl(
83
+ self,
84
+ agent_type: AgentType,
85
+ name: str,
86
+ instruction: str,
87
+ *,
88
+ servers: List[str] = [],
89
+ model: Optional[str] = None,
90
+ use_history: bool = True,
91
+ request_params: RequestParams | None = None,
92
+ human_input: bool = False,
93
+ **extra_kwargs,
94
+ ) -> Callable[[AgentCallable[P, R]], DecoratedAgentProtocol[P, R]]:
95
+ """
96
+ Core implementation for agent decorators with common behavior and type safety.
97
+
98
+ Args:
99
+ agent_type: Type of agent to create
100
+ name: Name of the agent
101
+ instruction: Base instruction for the agent
102
+ servers: List of server names the agent should connect to
103
+ model: Model specification string
104
+ use_history: Whether to maintain conversation history
105
+ request_params: Additional request parameters for the LLM
106
+ human_input: Whether to enable human input capabilities
107
+ **extra_kwargs: Additional agent/workflow-specific parameters
108
+ """
109
+
110
+ def decorator(func: AgentCallable[P, R]) -> DecoratedAgentProtocol[P, R]:
111
+ is_async = inspect.iscoroutinefunction(func)
112
+
113
+ # Handle both async and sync functions consistently
114
+ if is_async:
115
+
116
+ @wraps(func)
117
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
118
+ # Call the original function
119
+ return await func(*args, **kwargs)
120
+ else:
121
+
122
+ @wraps(func)
123
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
124
+ # Call the original function
125
+ return func(*args, **kwargs)
126
+
127
+ # Create agent configuration
128
+ config = AgentConfig(
129
+ name=name,
130
+ instruction=instruction,
131
+ servers=servers,
132
+ model=model,
133
+ use_history=use_history,
134
+ human_input=human_input,
135
+ )
136
+
137
+ # Update request params if provided
138
+ if request_params:
139
+ config.default_request_params = request_params
140
+
141
+ # Store metadata on the wrapper function
142
+ agent_data = {
143
+ "config": config,
144
+ "type": agent_type.value,
145
+ "func": func,
146
+ }
147
+
148
+ # Add extra parameters specific to this agent type
149
+ for key, value in extra_kwargs.items():
150
+ agent_data[key] = value
151
+
152
+ # Store the configuration in the FastAgent instance
153
+ self.agents[name] = agent_data
154
+
155
+ # Store type information for IDE support
156
+ setattr(wrapper, "_agent_type", agent_type)
157
+ setattr(wrapper, "_agent_config", config)
158
+ for key, value in extra_kwargs.items():
159
+ setattr(wrapper, f"_{key}", value)
160
+
161
+ return cast("DecoratedAgentProtocol[P, R]", wrapper)
162
+
163
+ return decorator
164
+
165
+
166
+ def agent(
167
+ self,
168
+ name: str = "default",
169
+ instruction_or_kwarg: Optional[str] = None,
170
+ *,
171
+ instruction: str = "You are a helpful agent.",
172
+ servers: List[str] = [],
173
+ model: Optional[str] = None,
174
+ use_history: bool = True,
175
+ request_params: RequestParams | None = None,
176
+ human_input: bool = False,
177
+ ) -> Callable[[AgentCallable[P, R]], DecoratedAgentProtocol[P, R]]:
178
+ """
179
+ Decorator to create and register a standard agent with type-safe signature.
180
+
181
+ Args:
182
+ name: Name of the agent
183
+ instruction_or_kwarg: Optional positional parameter for instruction
184
+ instruction: Base instruction for the agent (keyword arg)
185
+ servers: List of server names the agent should connect to
186
+ model: Model specification string
187
+ use_history: Whether to maintain conversation history
188
+ request_params: Additional request parameters for the LLM
189
+ human_input: Whether to enable human input capabilities
190
+
191
+ Returns:
192
+ A decorator that registers the agent with proper type annotations
193
+ """
194
+ final_instruction = instruction_or_kwarg if instruction_or_kwarg is not None else instruction
195
+
196
+ return _decorator_impl(
197
+ self,
198
+ AgentType.BASIC,
199
+ name=name,
200
+ instruction=final_instruction,
201
+ servers=servers,
202
+ model=model,
203
+ use_history=use_history,
204
+ request_params=request_params,
205
+ human_input=human_input,
206
+ )
207
+
208
+
209
+ def orchestrator(
210
+ self,
211
+ name: str,
212
+ *,
213
+ agents: List[str],
214
+ instruction: Optional[str] = None,
215
+ model: Optional[str] = None,
216
+ use_history: bool = False,
217
+ request_params: RequestParams | None = None,
218
+ human_input: bool = False,
219
+ plan_type: Literal["full", "iterative"] = "full",
220
+ max_iterations: int = 30,
221
+ ) -> Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]:
222
+ """
223
+ Decorator to create and register an orchestrator agent with type-safe signature.
224
+
225
+ Args:
226
+ name: Name of the orchestrator
227
+ agents: List of agent names this orchestrator can use
228
+ instruction: Base instruction for the orchestrator
229
+ model: Model specification string
230
+ use_history: Whether to maintain conversation history
231
+ request_params: Additional request parameters for the LLM
232
+ human_input: Whether to enable human input capabilities
233
+ plan_type: Planning approach - "full" or "iterative"
234
+ max_iterations: Maximum number of planning iterations
235
+
236
+ Returns:
237
+ A decorator that registers the orchestrator with proper type annotations
238
+ """
239
+ default_instruction = """
240
+ You are an expert planner. Given an objective task and a list of Agents
241
+ (which are collections of capabilities), your job is to break down the objective
242
+ into a series of steps, which can be performed by these agents.
243
+ """
244
+
245
+ # Create final request params with max_iterations
246
+
247
+ return cast(
248
+ "Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]",
249
+ _decorator_impl(
250
+ self,
251
+ AgentType.ORCHESTRATOR,
252
+ name=name,
253
+ instruction=instruction or default_instruction,
254
+ servers=[], # Orchestrators don't connect to servers directly
255
+ model=model,
256
+ use_history=use_history,
257
+ request_params=request_params,
258
+ human_input=human_input,
259
+ child_agents=agents,
260
+ plan_type=plan_type,
261
+ max_iterations=max_iterations,
262
+ ),
263
+ )
264
+
265
+
266
+ def router(
267
+ self,
268
+ name: str,
269
+ *,
270
+ agents: List[str],
271
+ instruction: Optional[str] = None,
272
+ model: Optional[str] = None,
273
+ use_history: bool = False,
274
+ request_params: RequestParams | None = None,
275
+ human_input: bool = False,
276
+ ) -> Callable[[AgentCallable[P, R]], DecoratedRouterProtocol[P, R]]:
277
+ """
278
+ Decorator to create and register a router agent with type-safe signature.
279
+
280
+ Args:
281
+ name: Name of the router
282
+ agents: List of agent names this router can route to
283
+ instruction: Base instruction for the router
284
+ model: Model specification string
285
+ use_history: Whether to maintain conversation history
286
+ request_params: Additional request parameters for the LLM
287
+ human_input: Whether to enable human input capabilities
288
+
289
+ Returns:
290
+ A decorator that registers the router with proper type annotations
291
+ """
292
+ default_instruction = """
293
+ You are a router that determines which specialized agent should handle a given query.
294
+ Analyze the query and select the most appropriate agent to handle it.
295
+ """
296
+
297
+ return cast(
298
+ "Callable[[AgentCallable[P, R]], DecoratedRouterProtocol[P, R]]",
299
+ _decorator_impl(
300
+ self,
301
+ AgentType.ROUTER,
302
+ name=name,
303
+ instruction=instruction or default_instruction,
304
+ servers=[], # Routers don't connect to servers directly
305
+ model=model,
306
+ use_history=use_history,
307
+ request_params=request_params,
308
+ human_input=human_input,
309
+ router_agents=agents,
310
+ ),
311
+ )
312
+
313
+
314
+ def chain(
315
+ self,
316
+ name: str,
317
+ *,
318
+ sequence: List[str],
319
+ instruction: Optional[str] = None,
320
+ cumulative: bool = False,
321
+ ) -> Callable[[AgentCallable[P, R]], DecoratedChainProtocol[P, R]]:
322
+ """
323
+ Decorator to create and register a chain agent with type-safe signature.
324
+
325
+ Args:
326
+ name: Name of the chain
327
+ sequence: List of agent names in the chain, executed in sequence
328
+ instruction: Base instruction for the chain
329
+ cumulative: Whether to use cumulative mode (each agent sees all previous responses)
330
+
331
+ Returns:
332
+ A decorator that registers the chain with proper type annotations
333
+ """
334
+ # Validate sequence is not empty
335
+ if not sequence:
336
+ from mcp_agent.core.exceptions import AgentConfigError
337
+
338
+ raise AgentConfigError(f"Chain '{name}' requires at least one agent in the sequence")
339
+
340
+ default_instruction = """
341
+ You are a chain that processes requests through a series of specialized agents in sequence.
342
+ Pass the output of each agent to the next agent in the chain.
343
+ """
344
+
345
+ return cast(
346
+ "Callable[[AgentCallable[P, R]], DecoratedChainProtocol[P, R]]",
347
+ _decorator_impl(
348
+ self,
349
+ AgentType.CHAIN,
350
+ name=name,
351
+ instruction=instruction or default_instruction,
352
+ sequence=sequence,
353
+ cumulative=cumulative,
354
+ ),
355
+ )
356
+
357
+
358
+ def parallel(
359
+ self,
360
+ name: str,
361
+ *,
362
+ fan_out: List[str],
363
+ fan_in: str | None = None,
364
+ instruction: Optional[str] = None,
365
+ include_request: bool = True,
366
+ ) -> Callable[[AgentCallable[P, R]], DecoratedParallelProtocol[P, R]]:
367
+ """
368
+ Decorator to create and register a parallel agent with type-safe signature.
369
+
370
+ Args:
371
+ name: Name of the parallel agent
372
+ fan_out: List of agents to execute in parallel
373
+ fan_in: Agent to aggregate results
374
+ instruction: Base instruction for the parallel agent
375
+ include_request: Whether to include the original request when aggregating
376
+
377
+ Returns:
378
+ A decorator that registers the parallel agent with proper type annotations
379
+ """
380
+ default_instruction = """
381
+ You are a parallel processor that executes multiple agents simultaneously
382
+ and aggregates their results.
383
+ """
384
+
385
+ return cast(
386
+ "Callable[[AgentCallable[P, R]], DecoratedParallelProtocol[P, R]]",
387
+ _decorator_impl(
388
+ self,
389
+ AgentType.PARALLEL,
390
+ name=name,
391
+ instruction=instruction or default_instruction,
392
+ servers=[], # Parallel agents don't connect to servers directly
393
+ fan_in=fan_in,
394
+ fan_out=fan_out,
395
+ include_request=include_request,
396
+ ),
397
+ )
398
+
399
+
400
+ def evaluator_optimizer(
401
+ self,
402
+ name: str,
403
+ *,
404
+ generator: str,
405
+ evaluator: str,
406
+ instruction: Optional[str] = None,
407
+ min_rating: str = "GOOD",
408
+ max_refinements: int = 3,
409
+ ) -> Callable[[AgentCallable[P, R]], DecoratedEvaluatorOptimizerProtocol[P, R]]:
410
+ """
411
+ Decorator to create and register an evaluator-optimizer agent with type-safe signature.
412
+
413
+ Args:
414
+ name: Name of the evaluator-optimizer agent
415
+ generator: Name of the agent that generates responses
416
+ evaluator: Name of the agent that evaluates responses
417
+ instruction: Base instruction for the evaluator-optimizer
418
+ min_rating: Minimum acceptable quality rating (EXCELLENT, GOOD, FAIR, POOR)
419
+ max_refinements: Maximum number of refinement iterations
420
+
421
+ Returns:
422
+ A decorator that registers the evaluator-optimizer with proper type annotations
423
+ """
424
+ default_instruction = """
425
+ You implement an iterative refinement process where content is generated,
426
+ evaluated for quality, and then refined based on specific feedback until
427
+ it reaches an acceptable quality standard.
428
+ """
429
+
430
+ return cast(
431
+ "Callable[[AgentCallable[P, R]], DecoratedEvaluatorOptimizerProtocol[P, R]]",
432
+ _decorator_impl(
433
+ self,
434
+ AgentType.EVALUATOR_OPTIMIZER,
435
+ name=name,
436
+ instruction=instruction or default_instruction,
437
+ servers=[], # Evaluator-optimizer doesn't connect to servers directly
438
+ generator=generator,
439
+ evaluator=evaluator,
440
+ min_rating=min_rating,
441
+ max_refinements=max_refinements,
442
+ ),
443
+ )