fast-agent-mcp 0.4.7__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.
- fast_agent/__init__.py +183 -0
- fast_agent/acp/__init__.py +19 -0
- fast_agent/acp/acp_aware_mixin.py +304 -0
- fast_agent/acp/acp_context.py +437 -0
- fast_agent/acp/content_conversion.py +136 -0
- fast_agent/acp/filesystem_runtime.py +427 -0
- fast_agent/acp/permission_store.py +269 -0
- fast_agent/acp/server/__init__.py +5 -0
- fast_agent/acp/server/agent_acp_server.py +1472 -0
- fast_agent/acp/slash_commands.py +1050 -0
- fast_agent/acp/terminal_runtime.py +408 -0
- fast_agent/acp/tool_permission_adapter.py +125 -0
- fast_agent/acp/tool_permissions.py +474 -0
- fast_agent/acp/tool_progress.py +814 -0
- fast_agent/agents/__init__.py +85 -0
- fast_agent/agents/agent_types.py +64 -0
- fast_agent/agents/llm_agent.py +350 -0
- fast_agent/agents/llm_decorator.py +1139 -0
- fast_agent/agents/mcp_agent.py +1337 -0
- fast_agent/agents/tool_agent.py +271 -0
- fast_agent/agents/workflow/agents_as_tools_agent.py +849 -0
- fast_agent/agents/workflow/chain_agent.py +212 -0
- fast_agent/agents/workflow/evaluator_optimizer.py +380 -0
- fast_agent/agents/workflow/iterative_planner.py +652 -0
- fast_agent/agents/workflow/maker_agent.py +379 -0
- fast_agent/agents/workflow/orchestrator_models.py +218 -0
- fast_agent/agents/workflow/orchestrator_prompts.py +248 -0
- fast_agent/agents/workflow/parallel_agent.py +250 -0
- fast_agent/agents/workflow/router_agent.py +353 -0
- fast_agent/cli/__init__.py +0 -0
- fast_agent/cli/__main__.py +73 -0
- fast_agent/cli/commands/acp.py +159 -0
- fast_agent/cli/commands/auth.py +404 -0
- fast_agent/cli/commands/check_config.py +783 -0
- fast_agent/cli/commands/go.py +514 -0
- fast_agent/cli/commands/quickstart.py +557 -0
- fast_agent/cli/commands/serve.py +143 -0
- fast_agent/cli/commands/server_helpers.py +114 -0
- fast_agent/cli/commands/setup.py +174 -0
- fast_agent/cli/commands/url_parser.py +190 -0
- fast_agent/cli/constants.py +40 -0
- fast_agent/cli/main.py +115 -0
- fast_agent/cli/terminal.py +24 -0
- fast_agent/config.py +798 -0
- fast_agent/constants.py +41 -0
- fast_agent/context.py +279 -0
- fast_agent/context_dependent.py +50 -0
- fast_agent/core/__init__.py +92 -0
- fast_agent/core/agent_app.py +448 -0
- fast_agent/core/core_app.py +137 -0
- fast_agent/core/direct_decorators.py +784 -0
- fast_agent/core/direct_factory.py +620 -0
- fast_agent/core/error_handling.py +27 -0
- fast_agent/core/exceptions.py +90 -0
- fast_agent/core/executor/__init__.py +0 -0
- fast_agent/core/executor/executor.py +280 -0
- fast_agent/core/executor/task_registry.py +32 -0
- fast_agent/core/executor/workflow_signal.py +324 -0
- fast_agent/core/fastagent.py +1186 -0
- fast_agent/core/logging/__init__.py +5 -0
- fast_agent/core/logging/events.py +138 -0
- fast_agent/core/logging/json_serializer.py +164 -0
- fast_agent/core/logging/listeners.py +309 -0
- fast_agent/core/logging/logger.py +278 -0
- fast_agent/core/logging/transport.py +481 -0
- fast_agent/core/prompt.py +9 -0
- fast_agent/core/prompt_templates.py +183 -0
- fast_agent/core/validation.py +326 -0
- fast_agent/event_progress.py +62 -0
- fast_agent/history/history_exporter.py +49 -0
- fast_agent/human_input/__init__.py +47 -0
- fast_agent/human_input/elicitation_handler.py +123 -0
- fast_agent/human_input/elicitation_state.py +33 -0
- fast_agent/human_input/form_elements.py +59 -0
- fast_agent/human_input/form_fields.py +256 -0
- fast_agent/human_input/simple_form.py +113 -0
- fast_agent/human_input/types.py +40 -0
- fast_agent/interfaces.py +310 -0
- fast_agent/llm/__init__.py +9 -0
- fast_agent/llm/cancellation.py +22 -0
- fast_agent/llm/fastagent_llm.py +931 -0
- fast_agent/llm/internal/passthrough.py +161 -0
- fast_agent/llm/internal/playback.py +129 -0
- fast_agent/llm/internal/silent.py +41 -0
- fast_agent/llm/internal/slow.py +38 -0
- fast_agent/llm/memory.py +275 -0
- fast_agent/llm/model_database.py +490 -0
- fast_agent/llm/model_factory.py +388 -0
- fast_agent/llm/model_info.py +102 -0
- fast_agent/llm/prompt_utils.py +155 -0
- fast_agent/llm/provider/anthropic/anthropic_utils.py +84 -0
- fast_agent/llm/provider/anthropic/cache_planner.py +56 -0
- fast_agent/llm/provider/anthropic/llm_anthropic.py +796 -0
- fast_agent/llm/provider/anthropic/multipart_converter_anthropic.py +462 -0
- fast_agent/llm/provider/bedrock/bedrock_utils.py +218 -0
- fast_agent/llm/provider/bedrock/llm_bedrock.py +2207 -0
- fast_agent/llm/provider/bedrock/multipart_converter_bedrock.py +84 -0
- fast_agent/llm/provider/google/google_converter.py +466 -0
- fast_agent/llm/provider/google/llm_google_native.py +681 -0
- fast_agent/llm/provider/openai/llm_aliyun.py +31 -0
- fast_agent/llm/provider/openai/llm_azure.py +143 -0
- fast_agent/llm/provider/openai/llm_deepseek.py +76 -0
- fast_agent/llm/provider/openai/llm_generic.py +35 -0
- fast_agent/llm/provider/openai/llm_google_oai.py +32 -0
- fast_agent/llm/provider/openai/llm_groq.py +42 -0
- fast_agent/llm/provider/openai/llm_huggingface.py +85 -0
- fast_agent/llm/provider/openai/llm_openai.py +1195 -0
- fast_agent/llm/provider/openai/llm_openai_compatible.py +138 -0
- fast_agent/llm/provider/openai/llm_openrouter.py +45 -0
- fast_agent/llm/provider/openai/llm_tensorzero_openai.py +128 -0
- fast_agent/llm/provider/openai/llm_xai.py +38 -0
- fast_agent/llm/provider/openai/multipart_converter_openai.py +561 -0
- fast_agent/llm/provider/openai/openai_multipart.py +169 -0
- fast_agent/llm/provider/openai/openai_utils.py +67 -0
- fast_agent/llm/provider/openai/responses.py +133 -0
- fast_agent/llm/provider_key_manager.py +139 -0
- fast_agent/llm/provider_types.py +34 -0
- fast_agent/llm/request_params.py +61 -0
- fast_agent/llm/sampling_converter.py +98 -0
- fast_agent/llm/stream_types.py +9 -0
- fast_agent/llm/usage_tracking.py +445 -0
- fast_agent/mcp/__init__.py +56 -0
- fast_agent/mcp/common.py +26 -0
- fast_agent/mcp/elicitation_factory.py +84 -0
- fast_agent/mcp/elicitation_handlers.py +164 -0
- fast_agent/mcp/gen_client.py +83 -0
- fast_agent/mcp/helpers/__init__.py +36 -0
- fast_agent/mcp/helpers/content_helpers.py +352 -0
- fast_agent/mcp/helpers/server_config_helpers.py +25 -0
- fast_agent/mcp/hf_auth.py +147 -0
- fast_agent/mcp/interfaces.py +92 -0
- fast_agent/mcp/logger_textio.py +108 -0
- fast_agent/mcp/mcp_agent_client_session.py +411 -0
- fast_agent/mcp/mcp_aggregator.py +2175 -0
- fast_agent/mcp/mcp_connection_manager.py +723 -0
- fast_agent/mcp/mcp_content.py +262 -0
- fast_agent/mcp/mime_utils.py +108 -0
- fast_agent/mcp/oauth_client.py +509 -0
- fast_agent/mcp/prompt.py +159 -0
- fast_agent/mcp/prompt_message_extended.py +155 -0
- fast_agent/mcp/prompt_render.py +84 -0
- fast_agent/mcp/prompt_serialization.py +580 -0
- fast_agent/mcp/prompts/__init__.py +0 -0
- fast_agent/mcp/prompts/__main__.py +7 -0
- fast_agent/mcp/prompts/prompt_constants.py +18 -0
- fast_agent/mcp/prompts/prompt_helpers.py +238 -0
- fast_agent/mcp/prompts/prompt_load.py +186 -0
- fast_agent/mcp/prompts/prompt_server.py +552 -0
- fast_agent/mcp/prompts/prompt_template.py +438 -0
- fast_agent/mcp/resource_utils.py +215 -0
- fast_agent/mcp/sampling.py +200 -0
- fast_agent/mcp/server/__init__.py +4 -0
- fast_agent/mcp/server/agent_server.py +613 -0
- fast_agent/mcp/skybridge.py +44 -0
- fast_agent/mcp/sse_tracking.py +287 -0
- fast_agent/mcp/stdio_tracking_simple.py +59 -0
- fast_agent/mcp/streamable_http_tracking.py +309 -0
- fast_agent/mcp/tool_execution_handler.py +137 -0
- fast_agent/mcp/tool_permission_handler.py +88 -0
- fast_agent/mcp/transport_tracking.py +634 -0
- fast_agent/mcp/types.py +24 -0
- fast_agent/mcp/ui_agent.py +48 -0
- fast_agent/mcp/ui_mixin.py +209 -0
- fast_agent/mcp_server_registry.py +89 -0
- fast_agent/py.typed +0 -0
- fast_agent/resources/examples/data-analysis/analysis-campaign.py +189 -0
- fast_agent/resources/examples/data-analysis/analysis.py +68 -0
- fast_agent/resources/examples/data-analysis/fastagent.config.yaml +41 -0
- fast_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +1471 -0
- fast_agent/resources/examples/mcp/elicitations/elicitation_account_server.py +88 -0
- fast_agent/resources/examples/mcp/elicitations/elicitation_forms_server.py +297 -0
- fast_agent/resources/examples/mcp/elicitations/elicitation_game_server.py +164 -0
- fast_agent/resources/examples/mcp/elicitations/fastagent.config.yaml +35 -0
- fast_agent/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +17 -0
- fast_agent/resources/examples/mcp/elicitations/forms_demo.py +107 -0
- fast_agent/resources/examples/mcp/elicitations/game_character.py +65 -0
- fast_agent/resources/examples/mcp/elicitations/game_character_handler.py +256 -0
- fast_agent/resources/examples/mcp/elicitations/tool_call.py +21 -0
- fast_agent/resources/examples/mcp/state-transfer/agent_one.py +18 -0
- fast_agent/resources/examples/mcp/state-transfer/agent_two.py +18 -0
- fast_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +27 -0
- fast_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +15 -0
- fast_agent/resources/examples/researcher/fastagent.config.yaml +61 -0
- fast_agent/resources/examples/researcher/researcher-eval.py +53 -0
- fast_agent/resources/examples/researcher/researcher-imp.py +189 -0
- fast_agent/resources/examples/researcher/researcher.py +36 -0
- fast_agent/resources/examples/tensorzero/.env.sample +2 -0
- fast_agent/resources/examples/tensorzero/Makefile +31 -0
- fast_agent/resources/examples/tensorzero/README.md +56 -0
- fast_agent/resources/examples/tensorzero/agent.py +35 -0
- fast_agent/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
- fast_agent/resources/examples/tensorzero/demo_images/crab.png +0 -0
- fast_agent/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
- fast_agent/resources/examples/tensorzero/docker-compose.yml +105 -0
- fast_agent/resources/examples/tensorzero/fastagent.config.yaml +19 -0
- fast_agent/resources/examples/tensorzero/image_demo.py +67 -0
- fast_agent/resources/examples/tensorzero/mcp_server/Dockerfile +25 -0
- fast_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh +35 -0
- fast_agent/resources/examples/tensorzero/mcp_server/mcp_server.py +31 -0
- fast_agent/resources/examples/tensorzero/mcp_server/pyproject.toml +11 -0
- fast_agent/resources/examples/tensorzero/simple_agent.py +25 -0
- fast_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json +29 -0
- fast_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +11 -0
- fast_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +35 -0
- fast_agent/resources/examples/workflows/agents_as_tools_extended.py +73 -0
- fast_agent/resources/examples/workflows/agents_as_tools_simple.py +50 -0
- fast_agent/resources/examples/workflows/chaining.py +37 -0
- fast_agent/resources/examples/workflows/evaluator.py +77 -0
- fast_agent/resources/examples/workflows/fastagent.config.yaml +26 -0
- fast_agent/resources/examples/workflows/graded_report.md +89 -0
- fast_agent/resources/examples/workflows/human_input.py +28 -0
- fast_agent/resources/examples/workflows/maker.py +156 -0
- fast_agent/resources/examples/workflows/orchestrator.py +70 -0
- fast_agent/resources/examples/workflows/parallel.py +56 -0
- fast_agent/resources/examples/workflows/router.py +69 -0
- fast_agent/resources/examples/workflows/short_story.md +13 -0
- fast_agent/resources/examples/workflows/short_story.txt +19 -0
- fast_agent/resources/setup/.gitignore +30 -0
- fast_agent/resources/setup/agent.py +28 -0
- fast_agent/resources/setup/fastagent.config.yaml +65 -0
- fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
- fast_agent/resources/setup/pyproject.toml.tmpl +23 -0
- fast_agent/skills/__init__.py +9 -0
- fast_agent/skills/registry.py +235 -0
- fast_agent/tools/elicitation.py +369 -0
- fast_agent/tools/shell_runtime.py +402 -0
- fast_agent/types/__init__.py +59 -0
- fast_agent/types/conversation_summary.py +294 -0
- fast_agent/types/llm_stop_reason.py +78 -0
- fast_agent/types/message_search.py +249 -0
- fast_agent/ui/__init__.py +38 -0
- fast_agent/ui/console.py +59 -0
- fast_agent/ui/console_display.py +1080 -0
- fast_agent/ui/elicitation_form.py +946 -0
- fast_agent/ui/elicitation_style.py +59 -0
- fast_agent/ui/enhanced_prompt.py +1400 -0
- fast_agent/ui/history_display.py +734 -0
- fast_agent/ui/interactive_prompt.py +1199 -0
- fast_agent/ui/markdown_helpers.py +104 -0
- fast_agent/ui/markdown_truncator.py +1004 -0
- fast_agent/ui/mcp_display.py +857 -0
- fast_agent/ui/mcp_ui_utils.py +235 -0
- fast_agent/ui/mermaid_utils.py +169 -0
- fast_agent/ui/message_primitives.py +50 -0
- fast_agent/ui/notification_tracker.py +205 -0
- fast_agent/ui/plain_text_truncator.py +68 -0
- fast_agent/ui/progress_display.py +10 -0
- fast_agent/ui/rich_progress.py +195 -0
- fast_agent/ui/streaming.py +774 -0
- fast_agent/ui/streaming_buffer.py +449 -0
- fast_agent/ui/tool_display.py +422 -0
- fast_agent/ui/usage_display.py +204 -0
- fast_agent/utils/__init__.py +5 -0
- fast_agent/utils/reasoning_stream_parser.py +77 -0
- fast_agent/utils/time.py +22 -0
- fast_agent/workflow_telemetry.py +261 -0
- fast_agent_mcp-0.4.7.dist-info/METADATA +788 -0
- fast_agent_mcp-0.4.7.dist-info/RECORD +261 -0
- fast_agent_mcp-0.4.7.dist-info/WHEEL +4 -0
- fast_agent_mcp-0.4.7.dist-info/entry_points.txt +7 -0
- fast_agent_mcp-0.4.7.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,784 @@
|
|
|
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
|
+
from collections.abc import Coroutine
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import (
|
|
10
|
+
Any,
|
|
11
|
+
Awaitable,
|
|
12
|
+
Callable,
|
|
13
|
+
Literal,
|
|
14
|
+
ParamSpec,
|
|
15
|
+
Protocol,
|
|
16
|
+
TypeVar,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from mcp.client.session import ElicitationFnT
|
|
20
|
+
from pydantic import AnyUrl
|
|
21
|
+
|
|
22
|
+
from fast_agent.agents.agent_types import AgentConfig, AgentType
|
|
23
|
+
from fast_agent.agents.workflow.iterative_planner import ITERATIVE_PLAN_SYSTEM_PROMPT_TEMPLATE
|
|
24
|
+
from fast_agent.agents.workflow.router_agent import (
|
|
25
|
+
ROUTING_SYSTEM_INSTRUCTION,
|
|
26
|
+
)
|
|
27
|
+
from fast_agent.constants import DEFAULT_AGENT_INSTRUCTION
|
|
28
|
+
from fast_agent.skills import SkillManifest, SkillRegistry
|
|
29
|
+
from fast_agent.types import RequestParams
|
|
30
|
+
|
|
31
|
+
# Type variables for the decorated function
|
|
32
|
+
P = ParamSpec("P") # Parameters
|
|
33
|
+
R = TypeVar("R", covariant=True) # Return type
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Protocol for decorated agent functions
|
|
37
|
+
class DecoratedAgentProtocol(Protocol[P, R]):
|
|
38
|
+
"""Protocol defining the interface of a decorated agent function."""
|
|
39
|
+
|
|
40
|
+
_agent_type: AgentType
|
|
41
|
+
_agent_config: AgentConfig
|
|
42
|
+
|
|
43
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[R]: ...
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Protocol for orchestrator functions
|
|
47
|
+
class DecoratedOrchestratorProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
48
|
+
"""Protocol for decorated orchestrator functions with additional metadata."""
|
|
49
|
+
|
|
50
|
+
_child_agents: list[str]
|
|
51
|
+
_plan_type: Literal["full", "iterative"]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Protocol for router functions
|
|
55
|
+
class DecoratedRouterProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
56
|
+
"""Protocol for decorated router functions with additional metadata."""
|
|
57
|
+
|
|
58
|
+
_router_agents: list[str]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# Protocol for chain functions
|
|
62
|
+
class DecoratedChainProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
63
|
+
"""Protocol for decorated chain functions with additional metadata."""
|
|
64
|
+
|
|
65
|
+
_chain_agents: list[str]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Protocol for parallel functions
|
|
69
|
+
class DecoratedParallelProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
70
|
+
"""Protocol for decorated parallel functions with additional metadata."""
|
|
71
|
+
|
|
72
|
+
_fan_out: list[str]
|
|
73
|
+
_fan_in: str
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Protocol for evaluator-optimizer functions
|
|
77
|
+
class DecoratedEvaluatorOptimizerProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
78
|
+
"""Protocol for decorated evaluator-optimizer functions with additional metadata."""
|
|
79
|
+
|
|
80
|
+
_generator: str
|
|
81
|
+
_evaluator: str
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Protocol for maker functions
|
|
85
|
+
class DecoratedMakerProtocol(DecoratedAgentProtocol[P, R], Protocol):
|
|
86
|
+
"""Protocol for decorated MAKER functions with additional metadata."""
|
|
87
|
+
|
|
88
|
+
_worker: str
|
|
89
|
+
_k: int
|
|
90
|
+
_max_samples: int
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _fetch_url_content(url: str) -> str:
|
|
94
|
+
"""
|
|
95
|
+
Fetch content from a URL.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
url: The URL to fetch content from
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
The text content from the URL
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
requests.RequestException: If the URL cannot be fetched
|
|
105
|
+
UnicodeDecodeError: If the content cannot be decoded as UTF-8
|
|
106
|
+
"""
|
|
107
|
+
import requests
|
|
108
|
+
|
|
109
|
+
response = requests.get(url, timeout=10)
|
|
110
|
+
response.raise_for_status() # Raise exception for HTTP errors
|
|
111
|
+
return response.text
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _apply_templates(text: str) -> str:
|
|
115
|
+
"""
|
|
116
|
+
Apply template substitutions to instruction text.
|
|
117
|
+
|
|
118
|
+
Supported templates:
|
|
119
|
+
{{currentDate}} - Current date in format "24 July 2025"
|
|
120
|
+
{{url:https://...}} - Content fetched from the specified URL
|
|
121
|
+
|
|
122
|
+
Note: File templates ({{file:...}} and {{file_silent:...}}) are resolved later
|
|
123
|
+
during runtime to ensure they're relative to the workspaceRoot.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
text: The text to process
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Text with template substitutions applied
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
requests.RequestException: If a URL in {{url:...}} cannot be fetched
|
|
133
|
+
UnicodeDecodeError: If URL content cannot be decoded as UTF-8
|
|
134
|
+
"""
|
|
135
|
+
import re
|
|
136
|
+
from datetime import datetime
|
|
137
|
+
|
|
138
|
+
# Apply {{currentDate}} template
|
|
139
|
+
current_date = datetime.now().strftime("%d %B %Y")
|
|
140
|
+
text = text.replace("{{currentDate}}", current_date)
|
|
141
|
+
|
|
142
|
+
# Apply {{url:...}} templates
|
|
143
|
+
url_pattern = re.compile(r"\{\{url:(https?://[^}]+)\}\}")
|
|
144
|
+
|
|
145
|
+
def replace_url(match):
|
|
146
|
+
url = match.group(1)
|
|
147
|
+
return _fetch_url_content(url)
|
|
148
|
+
|
|
149
|
+
text = url_pattern.sub(replace_url, text)
|
|
150
|
+
|
|
151
|
+
return text
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _resolve_instruction(instruction: str | Path | AnyUrl) -> str:
|
|
155
|
+
"""
|
|
156
|
+
Resolve instruction from either a string, Path, or URL with template support.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
instruction: Either a string instruction, Path to a file, or URL containing the instruction
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
The resolved instruction string with templates applied
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
FileNotFoundError: If the Path doesn't exist
|
|
166
|
+
PermissionError: If the Path can't be read
|
|
167
|
+
UnicodeDecodeError: If the file/URL content can't be decoded as UTF-8
|
|
168
|
+
requests.RequestException: If the URL cannot be fetched
|
|
169
|
+
"""
|
|
170
|
+
if isinstance(instruction, Path):
|
|
171
|
+
text = instruction.read_text(encoding="utf-8")
|
|
172
|
+
elif isinstance(instruction, AnyUrl):
|
|
173
|
+
text = _fetch_url_content(str(instruction))
|
|
174
|
+
else:
|
|
175
|
+
text = instruction
|
|
176
|
+
|
|
177
|
+
# Apply template substitutions
|
|
178
|
+
return _apply_templates(text)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _decorator_impl(
|
|
182
|
+
self,
|
|
183
|
+
agent_type: AgentType,
|
|
184
|
+
name: str,
|
|
185
|
+
instruction: str,
|
|
186
|
+
*,
|
|
187
|
+
servers: list[str] = [],
|
|
188
|
+
model: str | None = None,
|
|
189
|
+
use_history: bool = True,
|
|
190
|
+
request_params: RequestParams | None = None,
|
|
191
|
+
human_input: bool = False,
|
|
192
|
+
default: bool = False,
|
|
193
|
+
tools: dict[str, list[str]] | None = None,
|
|
194
|
+
resources: dict[str, list[str]] | None = None,
|
|
195
|
+
prompts: dict[str, list[str]] | None = None,
|
|
196
|
+
skills: SkillManifest
|
|
197
|
+
| SkillRegistry
|
|
198
|
+
| Path
|
|
199
|
+
| str
|
|
200
|
+
| list[SkillManifest | SkillRegistry | Path | str | None]
|
|
201
|
+
| None = None,
|
|
202
|
+
**extra_kwargs,
|
|
203
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
204
|
+
"""
|
|
205
|
+
Core implementation for agent decorators with common behavior and type safety.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
agent_type: Type of agent to create
|
|
209
|
+
name: Name of the agent
|
|
210
|
+
instruction: Base instruction for the agent
|
|
211
|
+
servers: List of server names the agent should connect to
|
|
212
|
+
model: Model specification string
|
|
213
|
+
use_history: Whether to maintain conversation history
|
|
214
|
+
request_params: Additional request parameters for the LLM
|
|
215
|
+
human_input: Whether to enable human input capabilities
|
|
216
|
+
default: Whether to mark this as the default agent
|
|
217
|
+
**extra_kwargs: Additional agent/workflow-specific parameters
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
def decorator(func: Callable[P, Coroutine[Any, Any, R]]) -> Callable[P, Coroutine[Any, Any, R]]:
|
|
221
|
+
# Create agent configuration
|
|
222
|
+
config = AgentConfig(
|
|
223
|
+
name=name,
|
|
224
|
+
instruction=instruction,
|
|
225
|
+
servers=servers,
|
|
226
|
+
tools=tools,
|
|
227
|
+
resources=resources,
|
|
228
|
+
prompts=prompts,
|
|
229
|
+
skills=skills,
|
|
230
|
+
model=model,
|
|
231
|
+
use_history=use_history,
|
|
232
|
+
human_input=human_input,
|
|
233
|
+
default=default,
|
|
234
|
+
elicitation_handler=extra_kwargs.get("elicitation_handler"),
|
|
235
|
+
api_key=extra_kwargs.get("api_key"),
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Update request params if provided
|
|
239
|
+
if request_params:
|
|
240
|
+
config.default_request_params = request_params
|
|
241
|
+
|
|
242
|
+
# Store metadata in the registry
|
|
243
|
+
agent_data = {
|
|
244
|
+
"config": config,
|
|
245
|
+
"type": agent_type.value,
|
|
246
|
+
"func": func,
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Add extra parameters specific to this agent type
|
|
250
|
+
for key, value in extra_kwargs.items():
|
|
251
|
+
agent_data[key] = value
|
|
252
|
+
|
|
253
|
+
# Store the configuration in the FastAgent instance
|
|
254
|
+
self.agents[name] = agent_data
|
|
255
|
+
|
|
256
|
+
# Store type information on the function for IDE support
|
|
257
|
+
setattr(func, "_agent_type", agent_type)
|
|
258
|
+
setattr(func, "_agent_config", config)
|
|
259
|
+
for key, value in extra_kwargs.items():
|
|
260
|
+
setattr(func, f"_{key}", value)
|
|
261
|
+
|
|
262
|
+
return func
|
|
263
|
+
|
|
264
|
+
return decorator
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def agent(
|
|
268
|
+
self,
|
|
269
|
+
name: str = "default",
|
|
270
|
+
instruction_or_kwarg: str | Path | AnyUrl | None = None,
|
|
271
|
+
*,
|
|
272
|
+
instruction: str | Path | AnyUrl = DEFAULT_AGENT_INSTRUCTION,
|
|
273
|
+
agents: list[str] | None = None,
|
|
274
|
+
servers: list[str] = [],
|
|
275
|
+
tools: dict[str, list[str]] | None = None,
|
|
276
|
+
resources: dict[str, list[str]] | None = None,
|
|
277
|
+
prompts: dict[str, list[str]] | None = None,
|
|
278
|
+
skills: SkillManifest | SkillRegistry | Path | str | None = None,
|
|
279
|
+
model: str | None = None,
|
|
280
|
+
use_history: bool = True,
|
|
281
|
+
request_params: RequestParams | None = None,
|
|
282
|
+
human_input: bool = False,
|
|
283
|
+
default: bool = False,
|
|
284
|
+
elicitation_handler: ElicitationFnT | None = None,
|
|
285
|
+
api_key: str | None = None,
|
|
286
|
+
history_mode: Any | None = None,
|
|
287
|
+
max_parallel: int | None = None,
|
|
288
|
+
child_timeout_sec: int | None = None,
|
|
289
|
+
max_display_instances: int | None = None,
|
|
290
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
291
|
+
"""
|
|
292
|
+
Decorator to create and register a standard agent with type-safe signature.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
name: Name of the agent
|
|
296
|
+
instruction_or_kwarg: Optional positional parameter for instruction
|
|
297
|
+
instruction: Base instruction for the agent (keyword arg)
|
|
298
|
+
servers: List of server names the agent should connect to
|
|
299
|
+
tools: Optional list of tool names or patterns to include
|
|
300
|
+
resources: Optional list of resource names or patterns to include
|
|
301
|
+
prompts: Optional list of prompt names or patterns to include
|
|
302
|
+
model: Model specification string
|
|
303
|
+
use_history: Whether to maintain conversation history
|
|
304
|
+
request_params: Additional request parameters for the LLM
|
|
305
|
+
human_input: Whether to enable human input capabilities
|
|
306
|
+
default: Whether to mark this as the default agent
|
|
307
|
+
elicitation_handler: Custom elicitation handler function (ElicitationFnT)
|
|
308
|
+
api_key: Optional API key for the LLM provider
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
A decorator that registers the agent with proper type annotations
|
|
312
|
+
"""
|
|
313
|
+
final_instruction_raw = (
|
|
314
|
+
instruction_or_kwarg if instruction_or_kwarg is not None else instruction
|
|
315
|
+
)
|
|
316
|
+
final_instruction = _resolve_instruction(final_instruction_raw)
|
|
317
|
+
|
|
318
|
+
return _decorator_impl(
|
|
319
|
+
self,
|
|
320
|
+
AgentType.BASIC,
|
|
321
|
+
name=name,
|
|
322
|
+
instruction=final_instruction,
|
|
323
|
+
child_agents=agents,
|
|
324
|
+
servers=servers,
|
|
325
|
+
model=model,
|
|
326
|
+
use_history=use_history,
|
|
327
|
+
request_params=request_params,
|
|
328
|
+
human_input=human_input,
|
|
329
|
+
default=default,
|
|
330
|
+
elicitation_handler=elicitation_handler,
|
|
331
|
+
tools=tools,
|
|
332
|
+
resources=resources,
|
|
333
|
+
prompts=prompts,
|
|
334
|
+
skills=skills,
|
|
335
|
+
api_key=api_key,
|
|
336
|
+
agents_as_tools_options={
|
|
337
|
+
"history_mode": history_mode,
|
|
338
|
+
"max_parallel": max_parallel,
|
|
339
|
+
"child_timeout_sec": child_timeout_sec,
|
|
340
|
+
"max_display_instances": max_display_instances,
|
|
341
|
+
},
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def custom(
|
|
346
|
+
self,
|
|
347
|
+
cls,
|
|
348
|
+
name: str = "default",
|
|
349
|
+
instruction_or_kwarg: str | Path | AnyUrl | None = None,
|
|
350
|
+
*,
|
|
351
|
+
instruction: str | Path | AnyUrl = "You are a helpful agent.",
|
|
352
|
+
servers: list[str] = [],
|
|
353
|
+
tools: dict[str, list[str]] | None = None,
|
|
354
|
+
resources: dict[str, list[str]] | None = None,
|
|
355
|
+
prompts: dict[str, list[str]] | None = None,
|
|
356
|
+
skills: SkillManifest | SkillRegistry | Path | str | None = None,
|
|
357
|
+
model: str | None = None,
|
|
358
|
+
use_history: bool = True,
|
|
359
|
+
request_params: RequestParams | None = None,
|
|
360
|
+
human_input: bool = False,
|
|
361
|
+
default: bool = False,
|
|
362
|
+
elicitation_handler: ElicitationFnT | None = None,
|
|
363
|
+
api_key: str | None = None,
|
|
364
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
365
|
+
"""
|
|
366
|
+
Decorator to create and register a standard agent with type-safe signature.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
name: Name of the agent
|
|
370
|
+
instruction_or_kwarg: Optional positional parameter for instruction
|
|
371
|
+
instruction: Base instruction for the agent (keyword arg)
|
|
372
|
+
servers: List of server names the agent should connect to
|
|
373
|
+
model: Model specification string
|
|
374
|
+
use_history: Whether to maintain conversation history
|
|
375
|
+
request_params: Additional request parameters for the LLM
|
|
376
|
+
human_input: Whether to enable human input capabilities
|
|
377
|
+
elicitation_handler: Custom elicitation handler function (ElicitationFnT)
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
A decorator that registers the agent with proper type annotations
|
|
381
|
+
"""
|
|
382
|
+
final_instruction_raw = (
|
|
383
|
+
instruction_or_kwarg if instruction_or_kwarg is not None else instruction
|
|
384
|
+
)
|
|
385
|
+
final_instruction = _resolve_instruction(final_instruction_raw)
|
|
386
|
+
|
|
387
|
+
return _decorator_impl(
|
|
388
|
+
self,
|
|
389
|
+
AgentType.CUSTOM,
|
|
390
|
+
name=name,
|
|
391
|
+
instruction=final_instruction,
|
|
392
|
+
servers=servers,
|
|
393
|
+
model=model,
|
|
394
|
+
use_history=use_history,
|
|
395
|
+
request_params=request_params,
|
|
396
|
+
human_input=human_input,
|
|
397
|
+
agent_class=cls,
|
|
398
|
+
default=default,
|
|
399
|
+
elicitation_handler=elicitation_handler,
|
|
400
|
+
api_key=api_key,
|
|
401
|
+
tools=tools,
|
|
402
|
+
resources=resources,
|
|
403
|
+
prompts=prompts,
|
|
404
|
+
skills=skills,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
DEFAULT_INSTRUCTION_ORCHESTRATOR = """
|
|
409
|
+
You are an expert planner. Given an objective task and a list of Agents
|
|
410
|
+
(which are collections of capabilities), your job is to break down the objective
|
|
411
|
+
into a series of steps, which can be performed by these agents.
|
|
412
|
+
"""
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def orchestrator(
|
|
416
|
+
self,
|
|
417
|
+
name: str,
|
|
418
|
+
*,
|
|
419
|
+
agents: list[str],
|
|
420
|
+
instruction: str | Path | AnyUrl = DEFAULT_INSTRUCTION_ORCHESTRATOR,
|
|
421
|
+
model: str | None = None,
|
|
422
|
+
request_params: RequestParams | None = None,
|
|
423
|
+
use_history: bool = False,
|
|
424
|
+
human_input: bool = False,
|
|
425
|
+
plan_type: Literal["full", "iterative"] = "full",
|
|
426
|
+
plan_iterations: int = 5,
|
|
427
|
+
default: bool = False,
|
|
428
|
+
api_key: str | None = None,
|
|
429
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
430
|
+
"""
|
|
431
|
+
Decorator to create and register an orchestrator agent with type-safe signature.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
name: Name of the orchestrator
|
|
435
|
+
agents: List of agent names this orchestrator can use
|
|
436
|
+
instruction: Base instruction for the orchestrator
|
|
437
|
+
model: Model specification string
|
|
438
|
+
use_history: Whether to maintain conversation history
|
|
439
|
+
request_params: Additional request parameters for the LLM
|
|
440
|
+
human_input: Whether to enable human input capabilities
|
|
441
|
+
plan_type: Planning approach - "full" or "iterative"
|
|
442
|
+
plan_iterations: Maximum number of planning iterations
|
|
443
|
+
default: Whether to mark this as the default agent
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
A decorator that registers the orchestrator with proper type annotations
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
# Create final request params with plan_iterations
|
|
450
|
+
resolved_instruction = _resolve_instruction(instruction)
|
|
451
|
+
|
|
452
|
+
return _decorator_impl(
|
|
453
|
+
self,
|
|
454
|
+
AgentType.ORCHESTRATOR,
|
|
455
|
+
name=name,
|
|
456
|
+
instruction=resolved_instruction,
|
|
457
|
+
servers=[], # Orchestrators don't connect to servers directly
|
|
458
|
+
model=model,
|
|
459
|
+
use_history=use_history,
|
|
460
|
+
request_params=request_params,
|
|
461
|
+
human_input=human_input,
|
|
462
|
+
child_agents=agents,
|
|
463
|
+
plan_type=plan_type,
|
|
464
|
+
plan_iterations=plan_iterations,
|
|
465
|
+
default=default,
|
|
466
|
+
api_key=api_key,
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def iterative_planner(
|
|
471
|
+
self,
|
|
472
|
+
name: str,
|
|
473
|
+
*,
|
|
474
|
+
agents: list[str],
|
|
475
|
+
instruction: str | Path | AnyUrl = ITERATIVE_PLAN_SYSTEM_PROMPT_TEMPLATE,
|
|
476
|
+
model: str | None = None,
|
|
477
|
+
request_params: RequestParams | None = None,
|
|
478
|
+
plan_iterations: int = -1,
|
|
479
|
+
default: bool = False,
|
|
480
|
+
api_key: str | None = None,
|
|
481
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
482
|
+
"""
|
|
483
|
+
Decorator to create and register an orchestrator agent with type-safe signature.
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
name: Name of the orchestrator
|
|
487
|
+
agents: List of agent names this orchestrator can use
|
|
488
|
+
instruction: Base instruction for the orchestrator
|
|
489
|
+
model: Model specification string
|
|
490
|
+
use_history: Whether to maintain conversation history
|
|
491
|
+
request_params: Additional request parameters for the LLM
|
|
492
|
+
human_input: Whether to enable human input capabilities
|
|
493
|
+
plan_type: Planning approach - "full" or "iterative"
|
|
494
|
+
plan_iterations: Maximum number of planning iterations (0 for unlimited)
|
|
495
|
+
default: Whether to mark this as the default agent
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
A decorator that registers the orchestrator with proper type annotations
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
# Create final request params with plan_iterations
|
|
502
|
+
resolved_instruction = _resolve_instruction(instruction)
|
|
503
|
+
|
|
504
|
+
return _decorator_impl(
|
|
505
|
+
self,
|
|
506
|
+
AgentType.ITERATIVE_PLANNER,
|
|
507
|
+
name=name,
|
|
508
|
+
instruction=resolved_instruction,
|
|
509
|
+
servers=[], # Orchestrators don't connect to servers directly
|
|
510
|
+
model=model,
|
|
511
|
+
use_history=False,
|
|
512
|
+
request_params=request_params,
|
|
513
|
+
child_agents=agents,
|
|
514
|
+
plan_iterations=plan_iterations,
|
|
515
|
+
default=default,
|
|
516
|
+
api_key=api_key,
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def router(
|
|
521
|
+
self,
|
|
522
|
+
name: str,
|
|
523
|
+
*,
|
|
524
|
+
agents: list[str],
|
|
525
|
+
instruction: str | Path | AnyUrl | None = None,
|
|
526
|
+
servers: list[str] = [],
|
|
527
|
+
tools: dict[str, list[str]] | None = None,
|
|
528
|
+
resources: dict[str, list[str]] | None = None,
|
|
529
|
+
prompts: dict[str, list[str]] | None = None,
|
|
530
|
+
model: str | None = None,
|
|
531
|
+
use_history: bool = False,
|
|
532
|
+
request_params: RequestParams | None = None,
|
|
533
|
+
human_input: bool = False,
|
|
534
|
+
default: bool = False,
|
|
535
|
+
elicitation_handler: ElicitationFnT
|
|
536
|
+
| None = None, ## exclude from docs, decide whether allowable
|
|
537
|
+
api_key: str | None = None,
|
|
538
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
539
|
+
"""
|
|
540
|
+
Decorator to create and register a router agent with type-safe signature.
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
name: Name of the router
|
|
544
|
+
agents: List of agent names this router can route to
|
|
545
|
+
instruction: Base instruction for the router
|
|
546
|
+
model: Model specification string
|
|
547
|
+
use_history: Whether to maintain conversation history
|
|
548
|
+
request_params: Additional request parameters for the LLM
|
|
549
|
+
human_input: Whether to enable human input capabilities
|
|
550
|
+
default: Whether to mark this as the default agent
|
|
551
|
+
elicitation_handler: Custom elicitation handler function (ElicitationFnT)
|
|
552
|
+
|
|
553
|
+
Returns:
|
|
554
|
+
A decorator that registers the router with proper type annotations
|
|
555
|
+
"""
|
|
556
|
+
resolved_instruction = _resolve_instruction(instruction or ROUTING_SYSTEM_INSTRUCTION)
|
|
557
|
+
|
|
558
|
+
return _decorator_impl(
|
|
559
|
+
self,
|
|
560
|
+
AgentType.ROUTER,
|
|
561
|
+
name=name,
|
|
562
|
+
instruction=resolved_instruction,
|
|
563
|
+
servers=servers,
|
|
564
|
+
model=model,
|
|
565
|
+
use_history=use_history,
|
|
566
|
+
request_params=request_params,
|
|
567
|
+
human_input=human_input,
|
|
568
|
+
default=default,
|
|
569
|
+
router_agents=agents,
|
|
570
|
+
elicitation_handler=elicitation_handler,
|
|
571
|
+
api_key=api_key,
|
|
572
|
+
tools=tools,
|
|
573
|
+
prompts=prompts,
|
|
574
|
+
resources=resources,
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def chain(
|
|
579
|
+
self,
|
|
580
|
+
name: str,
|
|
581
|
+
*,
|
|
582
|
+
sequence: list[str],
|
|
583
|
+
instruction: str | Path | AnyUrl | None = None,
|
|
584
|
+
cumulative: bool = False,
|
|
585
|
+
default: bool = False,
|
|
586
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
587
|
+
"""
|
|
588
|
+
Decorator to create and register a chain agent with type-safe signature.
|
|
589
|
+
|
|
590
|
+
Args:
|
|
591
|
+
name: Name of the chain
|
|
592
|
+
sequence: List of agent names in the chain, executed in sequence
|
|
593
|
+
instruction: Base instruction for the chain
|
|
594
|
+
cumulative: Whether to use cumulative mode (each agent sees all previous responses)
|
|
595
|
+
default: Whether to mark this as the default agent
|
|
596
|
+
|
|
597
|
+
Returns:
|
|
598
|
+
A decorator that registers the chain with proper type annotations
|
|
599
|
+
"""
|
|
600
|
+
# Validate sequence is not empty
|
|
601
|
+
if not sequence:
|
|
602
|
+
from fast_agent.core.exceptions import AgentConfigError
|
|
603
|
+
|
|
604
|
+
raise AgentConfigError(f"Chain '{name}' requires at least one agent in the sequence")
|
|
605
|
+
|
|
606
|
+
default_instruction = """Chain processes requests through a series of agents in sequence, the output of each agent is passed to the next."""
|
|
607
|
+
resolved_instruction = _resolve_instruction(instruction or default_instruction)
|
|
608
|
+
|
|
609
|
+
return _decorator_impl(
|
|
610
|
+
self,
|
|
611
|
+
AgentType.CHAIN,
|
|
612
|
+
name=name,
|
|
613
|
+
instruction=resolved_instruction,
|
|
614
|
+
sequence=sequence,
|
|
615
|
+
cumulative=cumulative,
|
|
616
|
+
default=default,
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def parallel(
|
|
621
|
+
self,
|
|
622
|
+
name: str,
|
|
623
|
+
*,
|
|
624
|
+
fan_out: list[str],
|
|
625
|
+
fan_in: str | None = None,
|
|
626
|
+
instruction: str | Path | AnyUrl | None = None,
|
|
627
|
+
include_request: bool = True,
|
|
628
|
+
default: bool = False,
|
|
629
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
630
|
+
"""
|
|
631
|
+
Decorator to create and register a parallel agent with type-safe signature.
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
name: Name of the parallel agent
|
|
635
|
+
fan_out: List of agents to execute in parallel
|
|
636
|
+
fan_in: Agent to aggregate results
|
|
637
|
+
instruction: Base instruction for the parallel agent
|
|
638
|
+
include_request: Whether to include the original request when aggregating
|
|
639
|
+
default: Whether to mark this as the default agent
|
|
640
|
+
|
|
641
|
+
Returns:
|
|
642
|
+
A decorator that registers the parallel agent with proper type annotations
|
|
643
|
+
"""
|
|
644
|
+
default_instruction = """
|
|
645
|
+
You are a parallel processor that executes multiple agents simultaneously
|
|
646
|
+
and aggregates their results.
|
|
647
|
+
"""
|
|
648
|
+
resolved_instruction = _resolve_instruction(instruction or default_instruction)
|
|
649
|
+
|
|
650
|
+
return _decorator_impl(
|
|
651
|
+
self,
|
|
652
|
+
AgentType.PARALLEL,
|
|
653
|
+
name=name,
|
|
654
|
+
instruction=resolved_instruction,
|
|
655
|
+
servers=[], # Parallel agents don't connect to servers directly
|
|
656
|
+
fan_in=fan_in,
|
|
657
|
+
fan_out=fan_out,
|
|
658
|
+
include_request=include_request,
|
|
659
|
+
default=default,
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def evaluator_optimizer(
|
|
664
|
+
self,
|
|
665
|
+
name: str,
|
|
666
|
+
*,
|
|
667
|
+
generator: str,
|
|
668
|
+
evaluator: str,
|
|
669
|
+
instruction: str | Path | AnyUrl | None = None,
|
|
670
|
+
min_rating: str = "GOOD",
|
|
671
|
+
max_refinements: int = 3,
|
|
672
|
+
refinement_instruction: str | None = None,
|
|
673
|
+
default: bool = False,
|
|
674
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
675
|
+
"""
|
|
676
|
+
Decorator to create and register an evaluator-optimizer agent with type-safe signature.
|
|
677
|
+
|
|
678
|
+
Args:
|
|
679
|
+
name: Name of the evaluator-optimizer agent
|
|
680
|
+
generator: Name of the agent that generates responses
|
|
681
|
+
evaluator: Name of the agent that evaluates responses
|
|
682
|
+
instruction: Base instruction for the evaluator-optimizer
|
|
683
|
+
min_rating: Minimum acceptable quality rating (EXCELLENT, GOOD, FAIR, POOR)
|
|
684
|
+
max_refinements: Maximum number of refinement iterations
|
|
685
|
+
default: Whether to mark this as the default agent
|
|
686
|
+
|
|
687
|
+
Returns:
|
|
688
|
+
A decorator that registers the evaluator-optimizer with proper type annotations
|
|
689
|
+
"""
|
|
690
|
+
default_instruction = """
|
|
691
|
+
You implement an iterative refinement process where content is generated,
|
|
692
|
+
evaluated for quality, and then refined based on specific feedback until
|
|
693
|
+
it reaches an acceptable quality standard.
|
|
694
|
+
"""
|
|
695
|
+
resolved_instruction = _resolve_instruction(instruction or default_instruction)
|
|
696
|
+
|
|
697
|
+
return _decorator_impl(
|
|
698
|
+
self,
|
|
699
|
+
AgentType.EVALUATOR_OPTIMIZER,
|
|
700
|
+
name=name,
|
|
701
|
+
instruction=resolved_instruction,
|
|
702
|
+
servers=[], # Evaluator-optimizer doesn't connect to servers directly
|
|
703
|
+
generator=generator,
|
|
704
|
+
evaluator=evaluator,
|
|
705
|
+
min_rating=min_rating,
|
|
706
|
+
max_refinements=max_refinements,
|
|
707
|
+
refinement_instruction=refinement_instruction,
|
|
708
|
+
default=default,
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
def maker(
|
|
713
|
+
self,
|
|
714
|
+
name: str,
|
|
715
|
+
*,
|
|
716
|
+
worker: str,
|
|
717
|
+
k: int = 3,
|
|
718
|
+
max_samples: int = 50,
|
|
719
|
+
match_strategy: str = "exact",
|
|
720
|
+
red_flag_max_length: int | None = None,
|
|
721
|
+
instruction: str | Path | AnyUrl | None = None,
|
|
722
|
+
default: bool = False,
|
|
723
|
+
) -> Callable[[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]]:
|
|
724
|
+
"""
|
|
725
|
+
Decorator to create a MAKER agent for statistical error correction via voting.
|
|
726
|
+
|
|
727
|
+
MAKER: Massively decomposed Agentic processes with K-voting Error Reduction.
|
|
728
|
+
|
|
729
|
+
Based on the paper "Solving a Million-Step LLM Task with Zero Errors"
|
|
730
|
+
(arXiv:2511.09030). Implements first-to-ahead-by-k voting where multiple
|
|
731
|
+
samples are drawn from a worker agent, and the first response to achieve
|
|
732
|
+
a k-vote margin over alternatives wins.
|
|
733
|
+
|
|
734
|
+
This enables high reliability with cost-effective models by trading
|
|
735
|
+
compute (multiple samples) for accuracy (statistical consensus).
|
|
736
|
+
|
|
737
|
+
Args:
|
|
738
|
+
name: Name of the MAKER agent
|
|
739
|
+
worker: Name of the agent to sample from for voting
|
|
740
|
+
k: Margin required to declare winner (first-to-ahead-by-k).
|
|
741
|
+
Higher k = more reliable but more samples needed.
|
|
742
|
+
Default of 3 provides strong guarantees for most use cases.
|
|
743
|
+
max_samples: Maximum samples before falling back to plurality vote
|
|
744
|
+
match_strategy: How to compare responses for voting:
|
|
745
|
+
- "exact": Character-for-character match
|
|
746
|
+
- "normalized": Ignore whitespace and case differences
|
|
747
|
+
- "structured": Parse as JSON and compare structurally
|
|
748
|
+
red_flag_max_length: Discard responses longer than this (characters).
|
|
749
|
+
Per the paper, overly long responses correlate
|
|
750
|
+
with errors. None = no length limit.
|
|
751
|
+
instruction: Base instruction for the MAKER agent
|
|
752
|
+
default: Whether to mark this as the default agent
|
|
753
|
+
|
|
754
|
+
Returns:
|
|
755
|
+
A decorator that registers the MAKER agent
|
|
756
|
+
|
|
757
|
+
Example:
|
|
758
|
+
@fast.agent(name="calculator", instruction="Return only the numeric result")
|
|
759
|
+
@fast.maker(name="reliable_calc", worker="calculator", k=3)
|
|
760
|
+
async def main():
|
|
761
|
+
async with fast.run() as agent:
|
|
762
|
+
result = await agent.reliable_calc.send("What is 17 * 23?")
|
|
763
|
+
"""
|
|
764
|
+
default_instruction = """
|
|
765
|
+
MAKER: Massively decomposed Agentic processes with K-voting Error Reduction.
|
|
766
|
+
Implements statistical error correction through voting consensus.
|
|
767
|
+
Multiple samples are drawn and the first response to achieve a k-vote
|
|
768
|
+
margin wins, ensuring high reliability even with cost-effective models.
|
|
769
|
+
"""
|
|
770
|
+
resolved_instruction = _resolve_instruction(instruction or default_instruction)
|
|
771
|
+
|
|
772
|
+
return _decorator_impl(
|
|
773
|
+
self,
|
|
774
|
+
AgentType.MAKER,
|
|
775
|
+
name=name,
|
|
776
|
+
instruction=resolved_instruction,
|
|
777
|
+
servers=[], # MAKER doesn't connect to servers directly
|
|
778
|
+
worker=worker,
|
|
779
|
+
k=k,
|
|
780
|
+
max_samples=max_samples,
|
|
781
|
+
match_strategy=match_strategy,
|
|
782
|
+
red_flag_max_length=red_flag_max_length,
|
|
783
|
+
default=default,
|
|
784
|
+
)
|