fast-agent-mcp 0.3.1__py3-none-any.whl → 0.3.3__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.

fast_agent/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """fast-agent - An MCP native agent application framework"""
2
+ from typing import TYPE_CHECKING as _TYPE_CHECKING
2
3
 
3
4
  # Configuration and settings (safe - pure Pydantic models)
4
5
  from fast_agent.config import (
@@ -83,6 +84,11 @@ def __getattr__(name: str):
83
84
  raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
84
85
 
85
86
 
87
+ # Help static analyzers/IDEs resolve symbols and signatures without importing at runtime.
88
+ if _TYPE_CHECKING: # pragma: no cover - typing aid only
89
+ from fast_agent.core.fastagent import FastAgent as FastAgent # noqa: F401
90
+
91
+
86
92
  __all__ = [
87
93
  # Core fast-agent components (lazy loaded)
88
94
  "Core",
@@ -189,6 +189,7 @@ class LlmDecorator(AgentProtocol):
189
189
  Sequence[Union[str, PromptMessage, PromptMessageExtended]],
190
190
  ],
191
191
  request_params: RequestParams | None = None,
192
+ tools: List[Tool] | None = None,
192
193
  ) -> PromptMessageExtended:
193
194
  """
194
195
  Create a completion with the LLM using the provided messages.
@@ -212,7 +213,7 @@ class LlmDecorator(AgentProtocol):
212
213
  multipart_messages = normalize_to_extended_list(messages)
213
214
 
214
215
  with self._tracer.start_as_current_span(f"Agent: '{self._name}' generate"):
215
- return await self.generate_impl(multipart_messages, request_params, None)
216
+ return await self.generate_impl(multipart_messages, request_params, tools)
216
217
 
217
218
  async def generate_impl(
218
219
  self,
@@ -43,7 +43,6 @@ from fast_agent.constants import HUMAN_INPUT_TOOL_NAME
43
43
  from fast_agent.core.exceptions import PromptExitError
44
44
  from fast_agent.core.logging.logger import get_logger
45
45
  from fast_agent.interfaces import FastAgentLLMProtocol
46
- from fast_agent.mcp.helpers.content_helpers import normalize_to_extended_list
47
46
  from fast_agent.mcp.mcp_aggregator import MCPAggregator
48
47
  from fast_agent.tools.elicitation import (
49
48
  get_elicitation_tool,
@@ -624,12 +623,9 @@ class McpAgent(ABC, ToolAgent):
624
623
  Returns:
625
624
  An instance of the specified model, or None if coercion fails
626
625
  """
627
- assert self._llm
628
- # Normalize all input types to a list of PromptMessageExtended
629
- normalized_messages = normalize_to_extended_list(messages)
630
626
 
631
627
  with self._tracer.start_as_current_span(f"Agent: '{self._name}' structured"):
632
- return await self._llm.structured(normalized_messages, model, request_params)
628
+ return await super().structured(messages, model, request_params)
633
629
 
634
630
  async def apply_prompt_messages(
635
631
  self, prompts: List[PromptMessageExtended], request_params: RequestParams | None = None
@@ -97,7 +97,10 @@ class ToolAgent(LlmAgent):
97
97
  )
98
98
 
99
99
  if LlmStopReason.TOOL_USE == result.stop_reason:
100
- messages = [await self.run_tools(result)]
100
+ if self.config.use_history:
101
+ messages = [await self.run_tools(result)]
102
+ else:
103
+ messages.extend([result, await self.run_tools(result)])
101
104
  else:
102
105
  break
103
106
 
@@ -72,7 +72,7 @@ class TaskWithResult(Task):
72
72
  class StepResult(BaseModel):
73
73
  """Result of executing a step"""
74
74
 
75
- step: Step = Field(description="The step that was executed", default_factory=Step)
75
+ step: Step = Field(description="The step that was executed")
76
76
  task_results: List[TaskWithResult] = Field(
77
77
  description="Results of executing each task", default_factory=list
78
78
  )
@@ -104,7 +104,7 @@ def generate_server_name(url: str) -> str:
104
104
 
105
105
 
106
106
  def parse_server_urls(
107
- urls_param: str, auth_token: str = None
107
+ urls_param: str, auth_token: str | None = None
108
108
  ) -> List[Tuple[str, Literal["http", "sse"], str, Dict[str, str] | None]]:
109
109
  """
110
110
  Parse a comma-separated list of URLs into server configurations.
@@ -155,7 +155,7 @@ def generate_server_configs(
155
155
  Returns:
156
156
  Dictionary of server configurations
157
157
  """
158
- server_configs = {}
158
+ server_configs: Dict[str, Dict[str, str | Dict[str, str]]] = {}
159
159
  # Keep track of server name occurrences to handle collisions
160
160
  name_counts = {}
161
161
 
@@ -178,7 +178,7 @@ def generate_server_configs(
178
178
  final_name = f"{server_name}_{suffix}"
179
179
  name_counts[server_name] += 1
180
180
 
181
- config = {
181
+ config: Dict[str, str | Dict[str, str]] = {
182
182
  "transport": transport_type,
183
183
  "url": url,
184
184
  }
fast_agent/cli/main.py CHANGED
@@ -85,7 +85,13 @@ def main(
85
85
  Use --help with any command for detailed usage information.
86
86
  """
87
87
  application.verbosity = 1 if verbose else 0 if not quiet else -1
88
- application.console = application.console if color else None
88
+ if not color:
89
+ # Recreate consoles without color when --no-color is provided
90
+ from fast_agent.ui.console import console as base_console
91
+ from fast_agent.ui.console import error_console as base_error_console
92
+
93
+ application.console = base_console.__class__(color_system=None)
94
+ application.error_console = base_error_console.__class__(color_system=None, stderr=True)
89
95
 
90
96
  # Handle version flag
91
97
  if version:
fast_agent/config.py CHANGED
@@ -547,6 +547,8 @@ def get_settings(config_path: str | None = None) -> Settings:
547
547
  return _settings
548
548
 
549
549
  # Handle config path - convert string to Path if needed
550
+ config_file: Path | None
551
+ secrets_file: Path | None
550
552
  if config_path:
551
553
  config_file = Path(config_path)
552
554
  # If it's a relative path and doesn't exist, try finding it
@@ -2,14 +2,19 @@
2
2
  Core interfaces and decorators for fast-agent.
3
3
 
4
4
  Public API:
5
- - `Core`: The core application container (lazy-loaded)
5
+ - `Core`: The core application container (eagerly exported)
6
6
  - `FastAgent`: High-level, decorator-driven application class (lazy-loaded)
7
7
  - Decorators: `agent`, `custom`, `orchestrator`, `iterative_planner`,
8
8
  `router`, `chain`, `parallel`, `evaluator_optimizer` (lazy-loaded)
9
9
  """
10
10
 
11
+ from typing import TYPE_CHECKING as _TYPE_CHECKING
12
+
13
+ from .core_app import Core # Eager export for external applications
14
+
11
15
  __all__ = [
12
16
  "Core",
17
+ "AgentApp",
13
18
  "FastAgent",
14
19
  # Decorators
15
20
  "agent",
@@ -25,14 +30,14 @@ __all__ = [
25
30
 
26
31
  def __getattr__(name: str):
27
32
  # Lazy imports to avoid heavy dependencies and circular imports at init time
28
- if name == "Core":
29
- from .core_app import Core
30
-
31
- return Core
32
33
  if name == "FastAgent":
33
34
  from .fastagent import FastAgent
34
35
 
35
36
  return FastAgent
37
+ if name == "AgentApp":
38
+ from .agent_app import AgentApp
39
+
40
+ return AgentApp
36
41
 
37
42
  # Decorators from direct_decorators
38
43
  if name in {
@@ -50,3 +55,37 @@ def __getattr__(name: str):
50
55
  return getattr(_dd, name)
51
56
 
52
57
  raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
58
+
59
+
60
+ # Help static analyzers/IDEs resolve symbols and signatures without importing at runtime.
61
+ if _TYPE_CHECKING: # pragma: no cover - typing aid only
62
+ from .agent_app import AgentApp as AgentApp # noqa: F401
63
+ from .direct_decorators import (
64
+ agent as agent,
65
+ ) # noqa: F401
66
+ from .direct_decorators import (
67
+ chain as chain,
68
+ )
69
+ from .direct_decorators import (
70
+ custom as custom,
71
+ )
72
+ from .direct_decorators import (
73
+ evaluator_optimizer as evaluator_optimizer,
74
+ )
75
+ from .direct_decorators import (
76
+ iterative_planner as iterative_planner,
77
+ )
78
+ from .direct_decorators import (
79
+ orchestrator as orchestrator,
80
+ )
81
+ from .direct_decorators import (
82
+ parallel as parallel,
83
+ )
84
+ from .direct_decorators import (
85
+ router as router,
86
+ )
87
+ from .fastagent import FastAgent as FastAgent # noqa: F401
88
+
89
+
90
+ def __dir__(): # pragma: no cover - developer experience aid
91
+ return sorted(__all__)
@@ -186,7 +186,7 @@ def _decorator_impl(
186
186
  resources: Optional[Dict[str, List[str]]] = None,
187
187
  prompts: Optional[Dict[str, List[str]]] = None,
188
188
  **extra_kwargs,
189
- ) -> Callable[[AgentCallable[P, R]], DecoratedAgentProtocol[P, R]]:
189
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
190
190
  """
191
191
  Core implementation for agent decorators with common behavior and type safety.
192
192
 
@@ -203,7 +203,7 @@ def _decorator_impl(
203
203
  **extra_kwargs: Additional agent/workflow-specific parameters
204
204
  """
205
205
 
206
- def decorator(func: AgentCallable[P, R]) -> DecoratedAgentProtocol[P, R]:
206
+ def decorator(func: AgentCallable[P, R]) -> AgentCallable[P, R]:
207
207
  @wraps(func)
208
208
  def wrapper(*args: P.args, **kwargs: P.kwargs) -> Awaitable[R]:
209
209
  # Call the original function
@@ -249,7 +249,7 @@ def _decorator_impl(
249
249
  for key, value in extra_kwargs.items():
250
250
  setattr(wrapper, f"_{key}", value)
251
251
 
252
- return cast("DecoratedAgentProtocol[P, R]", wrapper)
252
+ return cast("AgentCallable[P, R]", wrapper)
253
253
 
254
254
  return decorator
255
255
 
@@ -271,7 +271,7 @@ def agent(
271
271
  default: bool = False,
272
272
  elicitation_handler: Optional[ElicitationFnT] = None,
273
273
  api_key: str | None = None,
274
- ) -> Callable[[AgentCallable[P, R]], DecoratedAgentProtocol[P, R]]:
274
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
275
275
  """
276
276
  Decorator to create and register a standard agent with type-safe signature.
277
277
 
@@ -336,7 +336,7 @@ def custom(
336
336
  default: bool = False,
337
337
  elicitation_handler: Optional[ElicitationFnT] = None,
338
338
  api_key: str | None = None,
339
- ) -> Callable[[AgentCallable[P, R]], DecoratedAgentProtocol[P, R]]:
339
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
340
340
  """
341
341
  Decorator to create and register a standard agent with type-safe signature.
342
342
 
@@ -400,7 +400,7 @@ def orchestrator(
400
400
  plan_iterations: int = 5,
401
401
  default: bool = False,
402
402
  api_key: str | None = None,
403
- ) -> Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]:
403
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
404
404
  """
405
405
  Decorator to create and register an orchestrator agent with type-safe signature.
406
406
 
@@ -423,24 +423,21 @@ def orchestrator(
423
423
  # Create final request params with plan_iterations
424
424
  resolved_instruction = _resolve_instruction(instruction)
425
425
 
426
- return cast(
427
- "Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]",
428
- _decorator_impl(
429
- self,
430
- AgentType.ORCHESTRATOR,
431
- name=name,
432
- instruction=resolved_instruction,
433
- servers=[], # Orchestrators don't connect to servers directly
434
- model=model,
435
- use_history=use_history,
436
- request_params=request_params,
437
- human_input=human_input,
438
- child_agents=agents,
439
- plan_type=plan_type,
440
- plan_iterations=plan_iterations,
441
- default=default,
442
- api_key=api_key,
443
- ),
426
+ return _decorator_impl(
427
+ self,
428
+ AgentType.ORCHESTRATOR,
429
+ name=name,
430
+ instruction=resolved_instruction,
431
+ servers=[], # Orchestrators don't connect to servers directly
432
+ model=model,
433
+ use_history=use_history,
434
+ request_params=request_params,
435
+ human_input=human_input,
436
+ child_agents=agents,
437
+ plan_type=plan_type,
438
+ plan_iterations=plan_iterations,
439
+ default=default,
440
+ api_key=api_key,
444
441
  )
445
442
 
446
443
 
@@ -455,7 +452,7 @@ def iterative_planner(
455
452
  plan_iterations: int = -1,
456
453
  default: bool = False,
457
454
  api_key: str | None = None,
458
- ) -> Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]:
455
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
459
456
  """
460
457
  Decorator to create and register an orchestrator agent with type-safe signature.
461
458
 
@@ -478,22 +475,19 @@ def iterative_planner(
478
475
  # Create final request params with plan_iterations
479
476
  resolved_instruction = _resolve_instruction(instruction)
480
477
 
481
- return cast(
482
- "Callable[[AgentCallable[P, R]], DecoratedOrchestratorProtocol[P, R]]",
483
- _decorator_impl(
484
- self,
485
- AgentType.ITERATIVE_PLANNER,
486
- name=name,
487
- instruction=resolved_instruction,
488
- servers=[], # Orchestrators don't connect to servers directly
489
- model=model,
490
- use_history=False,
491
- request_params=request_params,
492
- child_agents=agents,
493
- plan_iterations=plan_iterations,
494
- default=default,
495
- api_key=api_key,
496
- ),
478
+ return _decorator_impl(
479
+ self,
480
+ AgentType.ITERATIVE_PLANNER,
481
+ name=name,
482
+ instruction=resolved_instruction,
483
+ servers=[], # Orchestrators don't connect to servers directly
484
+ model=model,
485
+ use_history=False,
486
+ request_params=request_params,
487
+ child_agents=agents,
488
+ plan_iterations=plan_iterations,
489
+ default=default,
490
+ api_key=api_key,
497
491
  )
498
492
 
499
493
 
@@ -516,7 +510,7 @@ def router(
516
510
  ElicitationFnT
517
511
  ] = None, ## exclude from docs, decide whether allowable
518
512
  api_key: str | None = None,
519
- ) -> Callable[[AgentCallable[P, R]], DecoratedRouterProtocol[P, R]]:
513
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
520
514
  """
521
515
  Decorator to create and register a router agent with type-safe signature.
522
516
 
@@ -536,26 +530,23 @@ def router(
536
530
  """
537
531
  resolved_instruction = _resolve_instruction(instruction or ROUTING_SYSTEM_INSTRUCTION)
538
532
 
539
- return cast(
540
- "Callable[[AgentCallable[P, R]], DecoratedRouterProtocol[P, R]]",
541
- _decorator_impl(
542
- self,
543
- AgentType.ROUTER,
544
- name=name,
545
- instruction=resolved_instruction,
546
- servers=servers,
547
- model=model,
548
- use_history=use_history,
549
- request_params=request_params,
550
- human_input=human_input,
551
- default=default,
552
- router_agents=agents,
553
- elicitation_handler=elicitation_handler,
554
- api_key=api_key,
555
- tools=tools,
556
- prompts=prompts,
557
- resources=resources,
558
- ),
533
+ return _decorator_impl(
534
+ self,
535
+ AgentType.ROUTER,
536
+ name=name,
537
+ instruction=resolved_instruction,
538
+ servers=servers,
539
+ model=model,
540
+ use_history=use_history,
541
+ request_params=request_params,
542
+ human_input=human_input,
543
+ default=default,
544
+ router_agents=agents,
545
+ elicitation_handler=elicitation_handler,
546
+ api_key=api_key,
547
+ tools=tools,
548
+ prompts=prompts,
549
+ resources=resources,
559
550
  )
560
551
 
561
552
 
@@ -567,7 +558,7 @@ def chain(
567
558
  instruction: Optional[str | Path | AnyUrl] = None,
568
559
  cumulative: bool = False,
569
560
  default: bool = False,
570
- ) -> Callable[[AgentCallable[P, R]], DecoratedChainProtocol[P, R]]:
561
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
571
562
  """
572
563
  Decorator to create and register a chain agent with type-safe signature.
573
564
 
@@ -593,17 +584,14 @@ def chain(
593
584
  """
594
585
  resolved_instruction = _resolve_instruction(instruction or default_instruction)
595
586
 
596
- return cast(
597
- "Callable[[AgentCallable[P, R]], DecoratedChainProtocol[P, R]]",
598
- _decorator_impl(
599
- self,
600
- AgentType.CHAIN,
601
- name=name,
602
- instruction=resolved_instruction,
603
- sequence=sequence,
604
- cumulative=cumulative,
605
- default=default,
606
- ),
587
+ return _decorator_impl(
588
+ self,
589
+ AgentType.CHAIN,
590
+ name=name,
591
+ instruction=resolved_instruction,
592
+ sequence=sequence,
593
+ cumulative=cumulative,
594
+ default=default,
607
595
  )
608
596
 
609
597
 
@@ -616,7 +604,7 @@ def parallel(
616
604
  instruction: Optional[str | Path | AnyUrl] = None,
617
605
  include_request: bool = True,
618
606
  default: bool = False,
619
- ) -> Callable[[AgentCallable[P, R]], DecoratedParallelProtocol[P, R]]:
607
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
620
608
  """
621
609
  Decorator to create and register a parallel agent with type-safe signature.
622
610
 
@@ -637,19 +625,16 @@ def parallel(
637
625
  """
638
626
  resolved_instruction = _resolve_instruction(instruction or default_instruction)
639
627
 
640
- return cast(
641
- "Callable[[AgentCallable[P, R]], DecoratedParallelProtocol[P, R]]",
642
- _decorator_impl(
643
- self,
644
- AgentType.PARALLEL,
645
- name=name,
646
- instruction=resolved_instruction,
647
- servers=[], # Parallel agents don't connect to servers directly
648
- fan_in=fan_in,
649
- fan_out=fan_out,
650
- include_request=include_request,
651
- default=default,
652
- ),
628
+ return _decorator_impl(
629
+ self,
630
+ AgentType.PARALLEL,
631
+ name=name,
632
+ instruction=resolved_instruction,
633
+ servers=[], # Parallel agents don't connect to servers directly
634
+ fan_in=fan_in,
635
+ fan_out=fan_out,
636
+ include_request=include_request,
637
+ default=default,
653
638
  )
654
639
 
655
640
 
@@ -663,7 +648,7 @@ def evaluator_optimizer(
663
648
  min_rating: str = "GOOD",
664
649
  max_refinements: int = 3,
665
650
  default: bool = False,
666
- ) -> Callable[[AgentCallable[P, R]], DecoratedEvaluatorOptimizerProtocol[P, R]]:
651
+ ) -> Callable[[AgentCallable[P, R]], AgentCallable[P, R]]:
667
652
  """
668
653
  Decorator to create and register an evaluator-optimizer agent with type-safe signature.
669
654
 
@@ -686,18 +671,15 @@ def evaluator_optimizer(
686
671
  """
687
672
  resolved_instruction = _resolve_instruction(instruction or default_instruction)
688
673
 
689
- return cast(
690
- "Callable[[AgentCallable[P, R]], DecoratedEvaluatorOptimizerProtocol[P, R]]",
691
- _decorator_impl(
692
- self,
693
- AgentType.EVALUATOR_OPTIMIZER,
694
- name=name,
695
- instruction=resolved_instruction,
696
- servers=[], # Evaluator-optimizer doesn't connect to servers directly
697
- generator=generator,
698
- evaluator=evaluator,
699
- min_rating=min_rating,
700
- max_refinements=max_refinements,
701
- default=default,
702
- ),
674
+ return _decorator_impl(
675
+ self,
676
+ AgentType.EVALUATOR_OPTIMIZER,
677
+ name=name,
678
+ instruction=resolved_instruction,
679
+ servers=[], # Evaluator-optimizer doesn't connect to servers directly
680
+ generator=generator,
681
+ evaluator=evaluator,
682
+ min_rating=min_rating,
683
+ max_refinements=max_refinements,
684
+ default=default,
703
685
  )
@@ -5,7 +5,7 @@ Error handling utilities for agent operations.
5
5
  from rich import print
6
6
 
7
7
 
8
- def handle_error(e: Exception, error_type: str, suggestion: str = None) -> None:
8
+ def handle_error(e: Exception, error_type: str, suggestion: str | None = None) -> None:
9
9
  """
10
10
  Handle errors with consistent formatting and messaging.
11
11
 
@@ -10,7 +10,19 @@ import sys
10
10
  from contextlib import asynccontextmanager
11
11
  from importlib.metadata import version as get_version
12
12
  from pathlib import Path
13
- from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, TypeVar
13
+ from typing import (
14
+ TYPE_CHECKING,
15
+ Any,
16
+ AsyncIterator,
17
+ Awaitable,
18
+ Callable,
19
+ Dict,
20
+ List,
21
+ Literal,
22
+ Optional,
23
+ ParamSpec,
24
+ TypeVar,
25
+ )
14
26
 
15
27
  import yaml
16
28
  from opentelemetry import trace
@@ -67,6 +79,9 @@ from fast_agent.mcp.prompts.prompt_load import load_prompt_multipart
67
79
  from fast_agent.ui.usage_display import display_usage_report
68
80
 
69
81
  if TYPE_CHECKING:
82
+ from mcp.client.session import ElicitationFnT
83
+ from pydantic import AnyUrl
84
+
70
85
  from fast_agent.interfaces import AgentProtocol
71
86
  from fast_agent.types import PromptMessageExtended
72
87
 
@@ -250,7 +265,139 @@ class FastAgent:
250
265
  """Access the application context"""
251
266
  return self.app.context
252
267
 
253
- # Decorator methods with type-safe implementations
268
+ # Decorator methods with precise signatures for IDE completion
269
+ # Provide annotations so IDEs can discover these attributes on instances
270
+ if TYPE_CHECKING: # pragma: no cover - typing aid only
271
+ from pathlib import Path
272
+
273
+ from fast_agent.types import RequestParams
274
+
275
+ P = ParamSpec("P")
276
+ R = TypeVar("R")
277
+
278
+ def agent(
279
+ self,
280
+ name: str = "default",
281
+ instruction_or_kwarg: Optional[str | Path | AnyUrl] = None,
282
+ *,
283
+ instruction: str | Path | AnyUrl = "You are a helpful agent.",
284
+ servers: List[str] = [],
285
+ tools: Optional[Dict[str, List[str]]] = None,
286
+ resources: Optional[Dict[str, List[str]]] = None,
287
+ prompts: Optional[Dict[str, List[str]]] = None,
288
+ model: Optional[str] = None,
289
+ use_history: bool = True,
290
+ request_params: RequestParams | None = None,
291
+ human_input: bool = False,
292
+ default: bool = False,
293
+ elicitation_handler: Optional[ElicitationFnT] = None,
294
+ api_key: str | None = None,
295
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
296
+
297
+ def custom(
298
+ self,
299
+ cls,
300
+ name: str = "default",
301
+ instruction_or_kwarg: Optional[str | Path | AnyUrl] = None,
302
+ *,
303
+ instruction: str | Path | AnyUrl = "You are a helpful agent.",
304
+ servers: List[str] = [],
305
+ tools: Optional[Dict[str, List[str]]] = None,
306
+ resources: Optional[Dict[str, List[str]]] = None,
307
+ prompts: Optional[Dict[str, List[str]]] = None,
308
+ model: Optional[str] = None,
309
+ use_history: bool = True,
310
+ request_params: RequestParams | None = None,
311
+ human_input: bool = False,
312
+ default: bool = False,
313
+ elicitation_handler: Optional[ElicitationFnT] = None,
314
+ api_key: str | None = None,
315
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
316
+
317
+ def orchestrator(
318
+ self,
319
+ name: str,
320
+ *,
321
+ agents: List[str],
322
+ instruction: str
323
+ | Path
324
+ | AnyUrl = "You are an expert planner. Given an objective task and a list of Agents\n(which are collections of capabilities), your job is to break down the objective\ninto a series of steps, which can be performed by these agents.\n",
325
+ model: Optional[str] = None,
326
+ request_params: RequestParams | None = None,
327
+ use_history: bool = False,
328
+ human_input: bool = False,
329
+ plan_type: Literal["full", "iterative"] = "full",
330
+ plan_iterations: int = 5,
331
+ default: bool = False,
332
+ api_key: str | None = None,
333
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
334
+
335
+ def iterative_planner(
336
+ self,
337
+ name: str,
338
+ *,
339
+ agents: List[str],
340
+ instruction: str | Path | AnyUrl = "You are an expert planner. Plan iteratively.",
341
+ model: Optional[str] = None,
342
+ request_params: RequestParams | None = None,
343
+ plan_iterations: int = -1,
344
+ default: bool = False,
345
+ api_key: str | None = None,
346
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
347
+
348
+ def router(
349
+ self,
350
+ name: str,
351
+ *,
352
+ agents: List[str],
353
+ instruction: Optional[str | Path | AnyUrl] = None,
354
+ servers: List[str] = [],
355
+ tools: Optional[Dict[str, List[str]]] = None,
356
+ resources: Optional[Dict[str, List[str]]] = None,
357
+ prompts: Optional[Dict[str, List[str]]] = None,
358
+ model: Optional[str] = None,
359
+ use_history: bool = False,
360
+ request_params: RequestParams | None = None,
361
+ human_input: bool = False,
362
+ default: bool = False,
363
+ elicitation_handler: Optional[ElicitationFnT] = None,
364
+ api_key: str | None = None,
365
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
366
+
367
+ def chain(
368
+ self,
369
+ name: str,
370
+ *,
371
+ sequence: List[str],
372
+ instruction: Optional[str | Path | AnyUrl] = None,
373
+ cumulative: bool = False,
374
+ default: bool = False,
375
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
376
+
377
+ def parallel(
378
+ self,
379
+ name: str,
380
+ *,
381
+ fan_out: List[str],
382
+ fan_in: str | None = None,
383
+ instruction: Optional[str | Path | AnyUrl] = None,
384
+ include_request: bool = True,
385
+ default: bool = False,
386
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
387
+
388
+ def evaluator_optimizer(
389
+ self,
390
+ name: str,
391
+ *,
392
+ generator: str,
393
+ evaluator: str,
394
+ instruction: Optional[str | Path | AnyUrl] = None,
395
+ min_rating: str = "GOOD",
396
+ max_refinements: int = 3,
397
+ default: bool = False,
398
+ ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]: ...
399
+
400
+ # Runtime bindings (actual implementations)
254
401
  agent = agent_decorator
255
402
  custom = custom_decorator
256
403
  orchestrator = orchestrator_decorator
@@ -261,7 +408,7 @@ class FastAgent:
261
408
  evaluator_optimizer = evaluator_optimizer_decorator
262
409
 
263
410
  @asynccontextmanager
264
- async def run(self):
411
+ async def run(self) -> AsyncIterator["AgentApp"]:
265
412
  """
266
413
  Context manager for running the application.
267
414
  Initializes all registered agents.
@@ -281,15 +428,14 @@ class FastAgent:
281
428
  try:
282
429
  async with self.app.run():
283
430
  # Apply quiet mode if requested
284
- if (
285
- quiet_mode
286
- and hasattr(self.app.context, "config")
287
- and hasattr(self.app.context.config, "logger")
288
- ):
289
- # Update our app's config directly
290
- self.app.context.config.logger.progress_display = False
291
- self.app.context.config.logger.show_chat = False
292
- self.app.context.config.logger.show_tools = False
431
+ if quiet_mode:
432
+ cfg = self.app.context.config
433
+ if cfg is not None and cfg.logger is not None:
434
+ # Update our app's config directly
435
+ cfg_logger = cfg.logger
436
+ cfg_logger.progress_display = False
437
+ cfg_logger.show_chat = False
438
+ cfg_logger.show_tools = False
293
439
 
294
440
  # Directly disable the progress display singleton
295
441
  from fast_agent.ui.progress_display import progress_display
@@ -410,12 +556,12 @@ class FastAgent:
410
556
  try:
411
557
  # Get response from the agent
412
558
  agent = active_agents[agent_name]
413
- response = await agent.generate(prompt)
559
+ prompt_result = await agent.generate(prompt)
414
560
 
415
561
  # In quiet mode, just print the raw response
416
562
  # The chat display should already be turned off by the configuration
417
563
  if self.args.quiet:
418
- print(f"{response.last_text()}")
564
+ print(f"{prompt_result.last_text()}")
419
565
 
420
566
  raise SystemExit(0)
421
567
  except Exception as e:
@@ -563,7 +709,7 @@ class FastAgent:
563
709
  original_args.quiet if original_args and hasattr(original_args, "quiet") else False
564
710
  )
565
711
  self.args.model = None
566
- if hasattr(original_args, "model"):
712
+ if original_args is not None and hasattr(original_args, "model"):
567
713
  self.args.model = original_args.model
568
714
 
569
715
  # Run the application, which will detect the server flag and start server mode
@@ -5,12 +5,7 @@ Events and event filters for the logger module for the MCP Agent
5
5
  import logging
6
6
  import random
7
7
  from datetime import datetime
8
- from typing import (
9
- Any,
10
- Dict,
11
- Literal,
12
- Set,
13
- )
8
+ from typing import Any, Dict, Literal
14
9
 
15
10
  from pydantic import BaseModel, ConfigDict, Field
16
11
 
@@ -64,9 +59,9 @@ class EventFilter(BaseModel):
64
59
  - a minimum severity level (DEBUG < INFO < WARNING < ERROR)
65
60
  """
66
61
 
67
- types: Set[EventType] | None = Field(default_factory=set)
68
- names: Set[str] | None = Field(default_factory=set)
69
- namespaces: Set[str] | None = Field(default_factory=set)
62
+ types: set[EventType] = Field(default_factory=set)
63
+ names: set[str] = Field(default_factory=set)
64
+ namespaces: set[str] = Field(default_factory=set)
70
65
  min_level: EventType | None = "debug"
71
66
 
72
67
  def matches(self, event: Event) -> bool:
@@ -2,7 +2,7 @@
2
2
  XML formatting utilities for consistent prompt engineering across components.
3
3
  """
4
4
 
5
- from typing import Dict, List, Optional, Union
5
+ from typing import Dict, List, Optional, TypedDict
6
6
 
7
7
 
8
8
  def format_xml_tag(
@@ -100,10 +100,16 @@ def format_server_info(
100
100
  return format_fastagent_tag("server", f"\n{server_content}\n", {"name": server_name})
101
101
 
102
102
 
103
+ class ServerInfo(TypedDict, total=False):
104
+ name: str
105
+ description: str
106
+ tools: List[Dict[str, str]]
107
+
108
+
103
109
  def format_agent_info(
104
110
  agent_name: str,
105
111
  description: Optional[str] = None,
106
- servers: Optional[List[Dict[str, Union[str, List[Dict[str, str]]]]]] = None,
112
+ servers: Optional[List[ServerInfo]] = None,
107
113
  ) -> str:
108
114
  """
109
115
  Format agent information consistently across router and orchestrator modules.
@@ -133,8 +139,8 @@ def format_agent_info(
133
139
  server_tags = []
134
140
  for server in servers:
135
141
  server_name = server.get("name", "")
136
- server_desc = server.get("description", "")
137
- server_tools = server.get("tools", [])
142
+ server_desc = server.get("description")
143
+ server_tools = server.get("tools")
138
144
  server_tag = format_server_info(server_name, server_desc, server_tools)
139
145
  server_tags.append(server_tag)
140
146
 
@@ -291,6 +291,7 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
291
291
  request_params: RequestParams | None = None,
292
292
  structured_model: Type[ModelT] | None = None,
293
293
  tools: List[Tool] | None = None,
294
+ pre_messages: List[MessageParam] | None = None,
294
295
  ) -> PromptMessageExtended:
295
296
  """
296
297
  Process a query using an LLM and available tools.
@@ -304,7 +305,7 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
304
305
 
305
306
  try:
306
307
  anthropic = AsyncAnthropic(api_key=api_key, base_url=base_url)
307
- messages: List[MessageParam] = []
308
+ messages: List[MessageParam] = list(pre_messages) if pre_messages else []
308
309
  params = self.get_request_params(request_params)
309
310
  except AuthenticationError as e:
310
311
  raise ProviderKeyError(
@@ -312,7 +313,7 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
312
313
  "The configured Anthropic API key was rejected.\nPlease check that your API key is valid and not expired.",
313
314
  ) from e
314
315
 
315
- # Always include prompt messages, but only include conversation history
316
+ # Always include prompt messages, but only include conversation history if enabled
316
317
  messages.extend(self.history.get(include_completion_history=params.use_history))
317
318
  messages.append(message_param) # message_param is the current user turn
318
319
 
@@ -470,6 +471,9 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
470
471
  tools: List[Tool] | None = None,
471
472
  is_template: bool = False,
472
473
  ) -> PromptMessageExtended:
474
+ # Effective params for this turn
475
+ params = self.get_request_params(request_params)
476
+
473
477
  # Check the last message role
474
478
  last_message = multipart_messages[-1]
475
479
 
@@ -477,7 +481,7 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
477
481
  messages_to_add = (
478
482
  multipart_messages[:-1] if last_message.role == "user" else multipart_messages
479
483
  )
480
- converted = []
484
+ converted: List[MessageParam] = []
481
485
 
482
486
  # Get cache mode configuration
483
487
  cache_mode = self._get_cache_mode()
@@ -499,12 +503,19 @@ class AnthropicLLM(FastAgentLLM[MessageParam, Message]):
499
503
 
500
504
  converted.append(anthropic_msg)
501
505
 
502
- self.history.extend(converted, is_prompt=is_template)
506
+ # Persist prior only when history is enabled; otherwise inline for this call
507
+ pre_messages: List[MessageParam] | None = None
508
+ if params.use_history:
509
+ self.history.extend(converted, is_prompt=is_template)
510
+ else:
511
+ pre_messages = converted
503
512
 
504
513
  if last_message.role == "user":
505
514
  logger.debug("Last message in prompt is from user, generating assistant response")
506
515
  message_param = AnthropicConverter.convert_to_anthropic(last_message)
507
- return await self._anthropic_completion(message_param, request_params, tools=tools)
516
+ return await self._anthropic_completion(
517
+ message_param, request_params, tools=tools, pre_messages=pre_messages
518
+ )
508
519
  else:
509
520
  # For assistant messages: Return the last message content as text
510
521
  logger.debug("Last message in prompt is from assistant, returning it directly")
@@ -1192,6 +1192,7 @@ class BedrockLLM(FastAgentLLM[BedrockMessageParam, BedrockMessage]):
1192
1192
  message_param: BedrockMessageParam,
1193
1193
  request_params: RequestParams | None = None,
1194
1194
  tools: List[Tool] | None = None,
1195
+ pre_messages: List[BedrockMessageParam] | None = None,
1195
1196
  ) -> PromptMessageExtended:
1196
1197
  """
1197
1198
  Process a query using Bedrock and available tools.
@@ -1200,7 +1201,7 @@ class BedrockLLM(FastAgentLLM[BedrockMessageParam, BedrockMessage]):
1200
1201
  client = self._get_bedrock_runtime_client()
1201
1202
 
1202
1203
  try:
1203
- messages: List[BedrockMessageParam] = []
1204
+ messages: List[BedrockMessageParam] = list(pre_messages) if pre_messages else []
1204
1205
  params = self.get_request_params(request_params)
1205
1206
  except (ClientError, BotoCoreError) as e:
1206
1207
  error_msg = str(e)
@@ -1869,8 +1870,13 @@ class BedrockLLM(FastAgentLLM[BedrockMessageParam, BedrockMessage]):
1869
1870
  bedrock_msg = self._convert_multipart_to_bedrock_message(msg)
1870
1871
  converted.append(bedrock_msg)
1871
1872
 
1872
- # Add messages to history
1873
- self.history.extend(converted, is_prompt=is_template)
1873
+ # Only persist prior messages when history is enabled; otherwise inline for this call
1874
+ params = self.get_request_params(request_params)
1875
+ pre_messages: List[BedrockMessageParam] | None = None
1876
+ if params.use_history:
1877
+ self.history.extend(converted, is_prompt=is_template)
1878
+ else:
1879
+ pre_messages = converted
1874
1880
 
1875
1881
  if last_message.role == "assistant":
1876
1882
  # For assistant messages: Return the last message (no completion needed)
@@ -1884,8 +1890,10 @@ class BedrockLLM(FastAgentLLM[BedrockMessageParam, BedrockMessage]):
1884
1890
  # Convert the last user message to Bedrock message parameter format
1885
1891
  message_param = self._convert_multipart_to_bedrock_message(last_message)
1886
1892
 
1887
- # Call the refactored completion method directly
1888
- return await self._bedrock_completion(message_param, request_params, tools)
1893
+ # Call the completion method with optional pre_messages for no-history mode
1894
+ return await self._bedrock_completion(
1895
+ message_param, request_params, tools, pre_messages=pre_messages
1896
+ )
1889
1897
 
1890
1898
  def _generate_simplified_schema(self, model: Type[ModelT]) -> str:
1891
1899
  """Generates a simplified, human-readable schema with inline enum constraints."""
@@ -280,9 +280,15 @@ class GoogleNativeLLM(FastAgentLLM[types.Content, types.Content]):
280
280
  )
281
281
 
282
282
  if messages_to_add:
283
- # Convert prior messages to google.genai Content and store in provider history
283
+ # Convert prior messages to google.genai Content
284
284
  converted_prior = self._converter.convert_to_google_content(messages_to_add)
285
- self.history.extend(converted_prior, is_prompt=is_template)
285
+ # Only persist prior context when history is enabled; otherwise inline later
286
+ if request_params.use_history:
287
+ self.history.extend(converted_prior, is_prompt=is_template)
288
+ else:
289
+ # Prepend prior context directly to the turn message list
290
+ # This keeps the single-turn chain intact without relying on provider memory
291
+ pass
286
292
 
287
293
  if last_message.role == "assistant":
288
294
  # No generation required; the provided assistant message is the output
@@ -322,6 +328,11 @@ class GoogleNativeLLM(FastAgentLLM[types.Content, types.Content]):
322
328
  # convert_to_google_content returns a list; preserve order after tool responses
323
329
  turn_messages.extend(user_contents)
324
330
 
331
+ # If not using provider history, include prior messages inline for this turn
332
+ if messages_to_add and not request_params.use_history:
333
+ prior_contents = self._converter.convert_to_google_content(messages_to_add)
334
+ turn_messages = prior_contents + turn_messages
335
+
325
336
  # If we somehow have no provider-native parts, ensure we send an empty user content
326
337
  if not turn_messages:
327
338
  turn_messages.append(types.Content(role="user", parts=[types.Part.from_text("")]))
@@ -448,32 +448,41 @@ class OpenAILLM(FastAgentLLM[ChatCompletionMessageParam, ChatCompletionMessage])
448
448
  tools: List[Tool] | None = None,
449
449
  is_template: bool = False,
450
450
  ) -> PromptMessageExtended:
451
- # Reset tool call counter for new turn
451
+ # Determine effective params to respect use_history for this turn
452
+ req_params = self.get_request_params(request_params)
452
453
 
453
454
  last_message = multipart_messages[-1]
454
455
 
455
- # Add all previous messages to history (or all messages if last is from assistant)
456
- # if the last message is a "user" inference is required
456
+ # Prepare prior messages (everything before the last user message), or all if last is assistant
457
457
  messages_to_add = (
458
458
  multipart_messages[:-1] if last_message.role == "user" else multipart_messages
459
459
  )
460
- converted = []
460
+
461
+ converted_prior: List[ChatCompletionMessageParam] = []
461
462
  for msg in messages_to_add:
462
463
  # convert_to_openai now returns a list of messages
463
- converted.extend(OpenAIConverter.convert_to_openai(msg))
464
-
465
- self.history.extend(converted, is_prompt=is_template)
464
+ converted_prior.extend(OpenAIConverter.convert_to_openai(msg))
466
465
 
467
- if "assistant" == last_message.role:
466
+ # If the last message is from the assistant, no inference required
467
+ if last_message.role == "assistant":
468
468
  return last_message
469
469
 
470
- converted_messages = OpenAIConverter.convert_to_openai(last_message)
471
- if not converted_messages:
470
+ # Convert the last user message
471
+ converted_last = OpenAIConverter.convert_to_openai(last_message)
472
+ if not converted_last:
472
473
  # Fallback for empty conversion
473
- converted_messages = [{"role": "user", "content": ""}]
474
+ converted_last = [{"role": "user", "content": ""}]
475
+
476
+ # History-aware vs stateless turn construction
477
+ if req_params.use_history:
478
+ # Persist prior context to provider memory; send only the last message for this turn
479
+ self.history.extend(converted_prior, is_prompt=is_template)
480
+ turn_messages = converted_last
481
+ else:
482
+ # Do NOT persist; inline the full turn context to the provider call
483
+ turn_messages = converted_prior + converted_last
474
484
 
475
- # Call completion without additional messages (all messages are now in history)
476
- return await self._openai_completion(converted_messages, request_params, tools)
485
+ return await self._openai_completion(turn_messages, req_params, tools)
477
486
 
478
487
  def _prepare_api_request(
479
488
  self, messages, tools: List[ChatCompletionToolParam] | None, request_params: RequestParams
@@ -5,7 +5,7 @@ from contextlib import contextmanager
5
5
  from typing import Optional
6
6
 
7
7
  from rich.console import Console
8
- from rich.progress import Progress, SpinnerColumn, TextColumn
8
+ from rich.progress import Progress, SpinnerColumn, TaskID, TextColumn
9
9
 
10
10
  from fast_agent.event_progress import ProgressAction, ProgressEvent
11
11
  from fast_agent.ui.console import console as default_console
@@ -17,7 +17,7 @@ class RichProgressDisplay:
17
17
  def __init__(self, console: Optional[Console] = None) -> None:
18
18
  """Initialize the progress display."""
19
19
  self.console = console or default_console
20
- self._taskmap = {}
20
+ self._taskmap: dict[str, TaskID] = {}
21
21
  self._progress = Progress(
22
22
  SpinnerColumn(spinner_name="simpleDotsScrolling"),
23
23
  TextColumn(
@@ -134,11 +134,13 @@ class RichProgressDisplay:
134
134
  description = f"[{self._get_action_style(event.action)}]▎ {event.action.value:<15}"
135
135
 
136
136
  # Update basic task information
137
- update_kwargs = {
137
+ update_kwargs: dict[str, object] = {
138
138
  "description": description,
139
- "target": event.target or task_name, # Use task_name as fallback for target
140
- "details": event.details or "",
141
- "task_name": task_name,
139
+ "fields": {
140
+ "target": event.target or task_name, # Use task_name as fallback for target
141
+ "details": event.details or "",
142
+ "task_name": task_name,
143
+ },
142
144
  }
143
145
 
144
146
  # For TOOL_PROGRESS events, update progress if available
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>
6
6
  License: Apache License
@@ -1,5 +1,5 @@
1
- fast_agent/__init__.py,sha256=bmws6wJQefvfO0Cd5x9VLTI7RCdjF6NqZtWSj_14tv0,3349
2
- fast_agent/config.py,sha256=8CPbTctXGdSneAkMory5ZRXkUsUj4AyKnaf_nmEamQA,19886
1
+ fast_agent/__init__.py,sha256=sljPsYHqDmv5v0fBpQdhtwBm5IDyu37lwdSQA0IPEwQ,3628
2
+ fast_agent/config.py,sha256=RLCYW9k4lgnfJVc3JpBWJscOC2mHw35gkVGrBS46M-4,19945
3
3
  fast_agent/constants.py,sha256=d5EMSO2msRkjRFz8MgnnhpMnO3woqKP0EcQ4b_yI60w,235
4
4
  fast_agent/context.py,sha256=nBelOqehSH91z3aG2nYhwETP-biRzz-iuA2fqmKdHP8,7700
5
5
  fast_agent/context_dependent.py,sha256=KU1eydVBoIt4bYOZroqxDgE1AUexDaZi7hurE26QsF4,1584
@@ -10,35 +10,35 @@ fast_agent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  fast_agent/agents/__init__.py,sha256=kBI2VWTitLyWf8K3dFMyuE-K7Ufp7mkHBomM2K3I8H8,1128
11
11
  fast_agent/agents/agent_types.py,sha256=ugolD3lC2KxSfBYjjRf9HjNATZaFx1o4Fhjb15huSgk,1776
12
12
  fast_agent/agents/llm_agent.py,sha256=iuy3kO5Q-f9bm3tjYLG2Wurd0gK2sLhTfTkSnfVWzSw,8311
13
- fast_agent/agents/llm_decorator.py,sha256=yzaYqsT8lqey4dbZrv1oK9qUqf8I2RMPYiWOy0uVHqA,16443
14
- fast_agent/agents/mcp_agent.py,sha256=R-OeHu0dO61z0vQwtCqKL2WLs1o9kHdsu74Fu4ALaCM,35494
15
- fast_agent/agents/tool_agent.py,sha256=zSaVQH-mBICgE3ildeZx24i00u_KMOk5P4OuJBTiQ3g,6571
13
+ fast_agent/agents/llm_decorator.py,sha256=IhvMOZVjo1qT4GII0KP000VYTCprzBQBGZPbZwBIEd0,16485
14
+ fast_agent/agents/mcp_agent.py,sha256=BMSTcGd9_SdoyEGNGVAWXu8ubaE1TAeAMl-2c_wymQU,35240
15
+ fast_agent/agents/tool_agent.py,sha256=owGcc1an9P8jb8ZfNYjCsLK6lv85IL7friWcSbZxMIo,6717
16
16
  fast_agent/agents/workflow/chain_agent.py,sha256=Pd8dOH_YdKu3LXsKa4fwqzY_B2qVuhzdfCUiKi5v17s,6293
17
17
  fast_agent/agents/workflow/evaluator_optimizer.py,sha256=rhzazy8Aj-ydId6kmBC77TmtYZ5mirSe7eV6PPMWkBA,12040
18
18
  fast_agent/agents/workflow/iterative_planner.py,sha256=CTtDpK-YGrFFZMQQmFeE-2I_9-cZv23pNwUoh8w5voA,20478
19
- fast_agent/agents/workflow/orchestrator_models.py,sha256=X_hD66_YvdGIsNra3XWbVKj2KyNVL7usCdNsMsDXV3Q,7238
19
+ fast_agent/agents/workflow/orchestrator_models.py,sha256=VNnnVegnjimgiuL8ZhxkBPhg8tjbeJRGq2JAIl0FAbU,7216
20
20
  fast_agent/agents/workflow/orchestrator_prompts.py,sha256=EXKEI174sshkZyPPEnWbwwNafzSPuA39MXL7iqG9cWc,9106
21
21
  fast_agent/agents/workflow/parallel_agent.py,sha256=DlJXDURAfx-WBF297tKBLfH93gDFSAPUyEmJr7QNGyw,7476
22
22
  fast_agent/agents/workflow/router_agent.py,sha256=KWLOZMFI4YPn0fqzR001qLFbOe7DYxx-E2c0BgIgO-g,11081
23
23
  fast_agent/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  fast_agent/cli/__main__.py,sha256=VD-UuXvIHJtrDGgVVpsAZGJ_GfVTalSD1Kx9vzixzfM,1129
25
25
  fast_agent/cli/constants.py,sha256=KawdkaN289nVB02DKPB4IVUJ8-fohIUD0gLfOp0P7B8,551
26
- fast_agent/cli/main.py,sha256=EkNOpNobFW83fkzJL4lkdhtqOq7c_f55KFpBR9VrFTU,3905
26
+ fast_agent/cli/main.py,sha256=H3brvpmDGE0g4WCJc2-volADCjpPmh7cSjedSfzqfOQ,4242
27
27
  fast_agent/cli/terminal.py,sha256=tDN1fJ91Nc_wZJTNafkQuD7Z7gFscvo1PHh-t7Wl-5s,1066
28
28
  fast_agent/cli/commands/check_config.py,sha256=nMiOBs-Sc7XqUU6tLReLn1JPXHqjR0Kuz4rCa3mDXp0,22831
29
29
  fast_agent/cli/commands/go.py,sha256=VRiHq9h1UGIndLdQJMAwEM6bwTGy-h5n6w__bYCGaHM,15094
30
30
  fast_agent/cli/commands/quickstart.py,sha256=hQZYlvktPdDNdaZOZkBgcvi8u0bMW5yFhz4BLBZ251I,21175
31
31
  fast_agent/cli/commands/server_helpers.py,sha256=BmljUNLIcZdFpffYxEPfJf8rrX3JhTzMA7VONoZLAjM,3650
32
32
  fast_agent/cli/commands/setup.py,sha256=rCp5wUs5kjbHJqi3Jz9ByCpOSvJ7L4KB0hpcKB8qpCM,6377
33
- fast_agent/cli/commands/url_parser.py,sha256=ivWrsODeVO9GGERkaTawYIxZuf57uRga1gubwT3n3vU,5907
34
- fast_agent/core/__init__.py,sha256=RsHaeZTQmmNC6cd--kGsnu-jp053cr7h0TUMEnBcMQ0,1223
33
+ fast_agent/cli/commands/url_parser.py,sha256=v9KoprPBEEST5Fo7qXgbW50GC5vMpxFteKqAT6mFkdI,5991
34
+ fast_agent/core/__init__.py,sha256=CnEL3AiklrG7jc0O-8RaF8_PTwBoDaHfmbXo3hOqR-I,2371
35
35
  fast_agent/core/agent_app.py,sha256=cdzNwpb--SUNYbhkUX6RolqVnxJ5WSchxw5I4gFrvpk,16836
36
36
  fast_agent/core/core_app.py,sha256=_8Di00HD2BzWhCAaopAUS0Hzc7pg0249QUUfPuLZ36A,4266
37
- fast_agent/core/direct_decorators.py,sha256=eHhQfKLbeaoH-W0snzAVJRxga7wTNGXBk5DEJTAbZB8,23642
37
+ fast_agent/core/direct_decorators.py,sha256=0U4_qJl7pdom9mjQ5qwCeb0zBwc5hj-lKFF6zXs62sI,22621
38
38
  fast_agent/core/direct_factory.py,sha256=HGGnnF4Z9k_N3r0Iin_sp2Ch308To1oKX8JTKHjuUq0,21350
39
- fast_agent/core/error_handling.py,sha256=xoyS2kLe0eG0bj2eSJCJ2odIhGUve2SbDR7jP-A-uRw,624
39
+ fast_agent/core/error_handling.py,sha256=tZkO8LnXO-qf6jD8a12Pv5fD4NhnN1Ag5_tJ6DwbXjg,631
40
40
  fast_agent/core/exceptions.py,sha256=ENAD_qGG67foxy6vDkIvc-lgopIUQy6O7zvNPpPXaQg,2289
41
- fast_agent/core/fastagent.py,sha256=duxLEQMXdKqvKXAxbbe86_V7ZQR-etR-OMt-XfvLB1I,25351
41
+ fast_agent/core/fastagent.py,sha256=5f9jOteVVV7BzX3b_BsUSo_kdciVukVKw567uu-u3qE,30848
42
42
  fast_agent/core/prompt.py,sha256=qNUFlK3KtU7leYysYUglzBYQnEYiXu__iR_T8189zc0,203
43
43
  fast_agent/core/validation.py,sha256=GZ0hUTxkr5KMY1wr6_ifDy91Ycvcx384gZEMOwdie9w,12681
44
44
  fast_agent/core/executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -46,7 +46,7 @@ fast_agent/core/executor/executor.py,sha256=egmu1bBJmNjfkMZRdaF2CowyHu0t20TiroKB
46
46
  fast_agent/core/executor/task_registry.py,sha256=PCALFeYtkQrPBg4RBJnlA0aDI8nHclrNkHGUS4kV3W8,1242
47
47
  fast_agent/core/executor/workflow_signal.py,sha256=Cg1uZBk3fn8kXhPOg-wINNuVaf3v9pvLD6NbqWy5Z6E,11142
48
48
  fast_agent/core/logging/__init__.py,sha256=dFW2bbTtz45zebUuQs7RVi7mg1RJm4DHH6TGfBMhW14,167
49
- fast_agent/core/logging/events.py,sha256=kmk6sWxYm4DZGRRNVUi2cOL4X1Pr1cr535uBmStBZxo,4254
49
+ fast_agent/core/logging/events.py,sha256=WTjr26uIxtbxhnoLNPROVUIt0HNJrzK1g1fUMZ-zVsQ,4207
50
50
  fast_agent/core/logging/json_serializer.py,sha256=kQDkwTHIkHSQgbhDOJhMoetNvfJVMZGOScaKoLX8kmw,5797
51
51
  fast_agent/core/logging/listeners.py,sha256=dubbGJoieryyhXN-JF-GrjkW-dgMq93bElM-NBkwA_Q,9366
52
52
  fast_agent/core/logging/logger.py,sha256=L-hLfUGFCIABoNYDiUkNHWvFxL6j-6zn5Pc5E7aC44M,11074
@@ -64,7 +64,7 @@ fast_agent/llm/memory.py,sha256=POFoBVMHK0wX4oLd3Gz-6Ru3uC4kTCvAqsVQ77e7KJA,8551
64
64
  fast_agent/llm/model_database.py,sha256=CXpAncjfFGmzjVyvAaKE5QuvDoLwMWXqUHngv_4oDl8,12609
65
65
  fast_agent/llm/model_factory.py,sha256=0quhsqz816GxEM_vuRaJ4n6U8C3lp5KxtIphxepIXVI,12862
66
66
  fast_agent/llm/model_info.py,sha256=DAIMW70W-EFqNLIudhjHJE2gobHUAKg90gkwOPuaFUc,4125
67
- fast_agent/llm/prompt_utils.py,sha256=yWQHykoK13QRF7evHUKxVF0SpVLN-Bsft0Yixzvn0g0,4825
67
+ fast_agent/llm/prompt_utils.py,sha256=1WU67G-BFqftja5I8FKPMMzsvDk1K_1jDi9A9kkFdOg,4899
68
68
  fast_agent/llm/provider_key_manager.py,sha256=igzs1ghXsUp0wA4nJVVfWCWiYOib8Ux4jMGlhWbgXu8,3396
69
69
  fast_agent/llm/provider_types.py,sha256=Ya0MGo_4cE0oCwinqPvr9SJUwx4hEJ7CFbCrLB_27FI,1142
70
70
  fast_agent/llm/request_params.py,sha256=OW9WnQAD-I2fz2JzMsqPY2wwwHFG0SI4yAvC1WxTfNY,1735
@@ -75,19 +75,19 @@ fast_agent/llm/internal/playback.py,sha256=HzV0BitORA977_3OWAbMZjLZpIHBKt-_PeOO3
75
75
  fast_agent/llm/internal/silent.py,sha256=TVhjp0sEcPpR35n_QjYrMu0CKVX2humAt1GBR6y_itE,1563
76
76
  fast_agent/llm/internal/slow.py,sha256=MQf21cK7aM0yPN1_j1hSJRTEp4UGbrPo_sCP81WDcxQ,1310
77
77
  fast_agent/llm/provider/anthropic/anthropic_utils.py,sha256=zkeMpAlV9YW9pP1FObkyqR8wg8e-Xir9SCwsom94zao,3246
78
- fast_agent/llm/provider/anthropic/llm_anthropic.py,sha256=GGfNM9dTVy17YTGOxaat-YlJlW2iWi-pcBmVg_ejJPE,25288
78
+ fast_agent/llm/provider/anthropic/llm_anthropic.py,sha256=EYd3_xy0OwSz4vM6XRkmQyG62_hTho-bsKpcg7CL9JI,25797
79
79
  fast_agent/llm/provider/anthropic/multipart_converter_anthropic.py,sha256=fO6qoKvG2ede85CvdvMipOlATwLjbGKahvsu2OzJhvk,16460
80
80
  fast_agent/llm/provider/bedrock/bedrock_utils.py,sha256=mqWCCeB1gUQSL2KRUMqpFjvHZ0ZTJugCsd5YOrx6U30,7750
81
- fast_agent/llm/provider/bedrock/llm_bedrock.py,sha256=XGB4bGZt74nQnGz0LY4HOSffdaRbz-5UWXX6fyjPPmk,99755
81
+ fast_agent/llm/provider/bedrock/llm_bedrock.py,sha256=VSwl-UbU5Qh7umqNzQ5NofeO8p7aHhGl89eL4wTJchY,100199
82
82
  fast_agent/llm/provider/google/google_converter.py,sha256=iQZps4773Bc8SUODduLpfkVpT3J1rIg1bFgLQ2CCqZc,18926
83
- fast_agent/llm/provider/google/llm_google_native.py,sha256=jHJ3dXDltFE9tJhvPe8OuHardIHAJqmDrJkhYpYZkeY,18843
83
+ fast_agent/llm/provider/google/llm_google_native.py,sha256=Uzkz8GXH-tzRO1mHnO1N7qiLuPdQ5NFkRoSa9_3uAPc,19451
84
84
  fast_agent/llm/provider/openai/llm_aliyun.py,sha256=ti7VHTpwl0AG3ytwBERpDzVtacvCfamKnl2bAnTE96s,1213
85
85
  fast_agent/llm/provider/openai/llm_azure.py,sha256=O-TIEL6hGOArqRlvEjocaeW4OMUaelSnh6xpqhrrcHQ,6070
86
86
  fast_agent/llm/provider/openai/llm_deepseek.py,sha256=aAMX7pd1qDfl54Z9pLvJTVYETc4yKKMRYrEMiPIhd7w,3762
87
87
  fast_agent/llm/provider/openai/llm_generic.py,sha256=O_mmu3o9LeAZ6Kp405I-GfwrS8AuVkyX3tT6aCDCfLY,1168
88
88
  fast_agent/llm/provider/openai/llm_google_oai.py,sha256=u1yZVeDds9z2hvydz_kUpFe2RANTNwEtlPgB-OEmgrY,1095
89
89
  fast_agent/llm/provider/openai/llm_groq.py,sha256=trNSy3T94_fJWAhVn51iESP_J7sQh_23ufVegKKNHBs,5247
90
- fast_agent/llm/provider/openai/llm_openai.py,sha256=OW1IwDn9sKBoITwUZYc3kHNyRLzJnC4qYcBwVytG8eA,22196
90
+ fast_agent/llm/provider/openai/llm_openai.py,sha256=I4qcAjqUsMDRJtNdSmol57XYar8rj0mqV3VRtkOCZ_8,22681
91
91
  fast_agent/llm/provider/openai/llm_openrouter.py,sha256=RBTUkNBRqE8WoucCoVnXP5GhnMwc2tiRacXbMHVf1xM,1943
92
92
  fast_agent/llm/provider/openai/llm_tensorzero_openai.py,sha256=yrV0kZ2zRohErdjhvWGDTl0OnPi2SbuzY_8MchXiVTU,5466
93
93
  fast_agent/llm/provider/openai/llm_xai.py,sha256=fEyO9XlU3Ef1a-cXdJl0Qe-FmE562cA-UJOGvzqLO6M,1375
@@ -194,10 +194,10 @@ fast_agent/ui/interactive_prompt.py,sha256=lxY26PNBNihtccO4iI7CxIag_9CxEcbajbIPd
194
194
  fast_agent/ui/mcp_ui_utils.py,sha256=UVX-VZI7PaJ8JlYuWsletml4K3XrUGUFRn4lqFwsAWg,8099
195
195
  fast_agent/ui/mermaid_utils.py,sha256=MpcRyVCPMTwU1XeIxnyFg0fQLjcyXZduWRF8NhEqvXE,5332
196
196
  fast_agent/ui/progress_display.py,sha256=hajDob65PttiJ2mPS6FsCtnmTcnyvDWGn-UqQboXqkQ,361
197
- fast_agent/ui/rich_progress.py,sha256=vMeDD5cybsPf_0IjOM98U8TVaE_yYIOKZa8JnRgTYUo,7451
197
+ fast_agent/ui/rich_progress.py,sha256=jy6VuUOYFkWXdyvnRTSBPAmmNAP6TJDFw_lgbt_YYLo,7548
198
198
  fast_agent/ui/usage_display.py,sha256=ltJpn_sDzo8PDNSXWx-QdEUbQWUnhmajCItNt5mA5rM,7285
199
- fast_agent_mcp-0.3.1.dist-info/METADATA,sha256=PDf70TWXzCOk8dgPOwDBlb7v5yO8hb8-cQb-h6YgG_4,30462
200
- fast_agent_mcp-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
201
- fast_agent_mcp-0.3.1.dist-info/entry_points.txt,sha256=i6Ujja9J-hRxttOKqTYdbYP_tyaS4gLHg53vupoCSsg,199
202
- fast_agent_mcp-0.3.1.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
203
- fast_agent_mcp-0.3.1.dist-info/RECORD,,
199
+ fast_agent_mcp-0.3.3.dist-info/METADATA,sha256=OaL4vvtEurj2Cffo53cry42F1aGNlJxWGMkZj9qmDVg,30462
200
+ fast_agent_mcp-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
201
+ fast_agent_mcp-0.3.3.dist-info/entry_points.txt,sha256=i6Ujja9J-hRxttOKqTYdbYP_tyaS4gLHg53vupoCSsg,199
202
+ fast_agent_mcp-0.3.3.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
203
+ fast_agent_mcp-0.3.3.dist-info/RECORD,,