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,107 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quick Start: Elicitation Forms Demo
|
|
3
|
+
|
|
4
|
+
This example demonstrates the elicitation forms feature of fast-agent.
|
|
5
|
+
|
|
6
|
+
When Read Resource requests are sent to the MCP Server, it generates an Elicitation
|
|
7
|
+
which creates a form for the user to fill out.
|
|
8
|
+
The results are returned to the demo program which prints out the results in a rich format.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
|
|
13
|
+
from rich.console import Console
|
|
14
|
+
from rich.panel import Panel
|
|
15
|
+
|
|
16
|
+
from fast_agent import FastAgent
|
|
17
|
+
from fast_agent.mcp.helpers.content_helpers import get_resource_text
|
|
18
|
+
|
|
19
|
+
fast = FastAgent("Elicitation Forms Demo", quiet=True)
|
|
20
|
+
console = Console()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@fast.agent(
|
|
24
|
+
"forms-demo",
|
|
25
|
+
servers=[
|
|
26
|
+
"elicitation_forms_server",
|
|
27
|
+
],
|
|
28
|
+
)
|
|
29
|
+
async def main():
|
|
30
|
+
"""Run the improved forms demo showcasing all elicitation features."""
|
|
31
|
+
async with fast.run() as agent:
|
|
32
|
+
console.print("\n[bold cyan]Welcome to the Elicitation Forms Demo![/bold cyan]\n")
|
|
33
|
+
console.print("This demo shows how to collect structured data using MCP Elicitations.")
|
|
34
|
+
console.print("We'll present several forms and display the results collected for each.\n")
|
|
35
|
+
|
|
36
|
+
# Example 1: Event Registration
|
|
37
|
+
console.print("[bold yellow]Example 1: Event Registration Form[/bold yellow]")
|
|
38
|
+
console.print(
|
|
39
|
+
"[dim]Demonstrates: string validation, email format, URL format, date format, "
|
|
40
|
+
"multi-select enums[/dim]"
|
|
41
|
+
)
|
|
42
|
+
result = await agent["forms-demo"].get_resource("elicitation://event-registration")
|
|
43
|
+
|
|
44
|
+
if result_text := get_resource_text(result):
|
|
45
|
+
panel = Panel(
|
|
46
|
+
result_text,
|
|
47
|
+
title="🎫 Registration Confirmation",
|
|
48
|
+
border_style="green",
|
|
49
|
+
expand=False,
|
|
50
|
+
)
|
|
51
|
+
console.print(panel)
|
|
52
|
+
else:
|
|
53
|
+
console.print("[red]No registration data received[/red]")
|
|
54
|
+
|
|
55
|
+
# Example 2: Product Review
|
|
56
|
+
console.print("[bold yellow]Example 2: Product Review Form[/bold yellow]")
|
|
57
|
+
console.print(
|
|
58
|
+
"[dim]Demonstrates: number validation (range), radio selection, multiline text[/dim]"
|
|
59
|
+
)
|
|
60
|
+
result = await agent.get_resource("elicitation://product-review")
|
|
61
|
+
|
|
62
|
+
if result_text := get_resource_text(result):
|
|
63
|
+
review_panel = Panel(
|
|
64
|
+
result_text, title="🛍️ Product Review", border_style="cyan", expand=False
|
|
65
|
+
)
|
|
66
|
+
console.print(review_panel)
|
|
67
|
+
|
|
68
|
+
# Example 3: Account Settings
|
|
69
|
+
console.print("[bold yellow]Example 3: Account Settings Form[/bold yellow]")
|
|
70
|
+
console.print(
|
|
71
|
+
"[dim]Demonstrates: boolean selections, radio selection, number validation[/dim]"
|
|
72
|
+
)
|
|
73
|
+
result = await agent.get_resource("elicitation://account-settings")
|
|
74
|
+
|
|
75
|
+
if result_text := get_resource_text(result):
|
|
76
|
+
settings_panel = Panel(
|
|
77
|
+
result_text, title="⚙️ Account Settings", border_style="blue", expand=False
|
|
78
|
+
)
|
|
79
|
+
console.print(settings_panel)
|
|
80
|
+
|
|
81
|
+
# Example 4: Service Appointment
|
|
82
|
+
console.print("[bold yellow]Example 4: Service Appointment Booking[/bold yellow]")
|
|
83
|
+
console.print(
|
|
84
|
+
"[dim]Demonstrates: string validation, radio selection, boolean, datetime format[/dim]"
|
|
85
|
+
)
|
|
86
|
+
result = await agent.get_resource("elicitation://service-appointment")
|
|
87
|
+
|
|
88
|
+
if result_text := get_resource_text(result):
|
|
89
|
+
appointment_panel = Panel(
|
|
90
|
+
result_text, title="🔧 Appointment Confirmed", border_style="magenta", expand=False
|
|
91
|
+
)
|
|
92
|
+
console.print(appointment_panel)
|
|
93
|
+
|
|
94
|
+
console.print("\n[bold green]✅ Demo Complete![/bold green]")
|
|
95
|
+
console.print("\n[bold cyan]Features Demonstrated:[/bold cyan]")
|
|
96
|
+
console.print("• [green]String validation[/green] (min/max length)")
|
|
97
|
+
console.print("• [green]Number validation[/green] (range constraints)")
|
|
98
|
+
console.print("• [green]Radio selections[/green] (enum dropdowns)")
|
|
99
|
+
console.print("• [green]Multi-select enums[/green] (checkbox lists)")
|
|
100
|
+
console.print("• [green]Boolean selections[/green] (checkboxes)")
|
|
101
|
+
console.print("• [green]Format validation[/green] (email, URL, date, datetime)")
|
|
102
|
+
console.print("• [green]Multiline text[/green] (expandable text areas)")
|
|
103
|
+
console.print("\nThese forms demonstrate natural, user-friendly data collection patterns!")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Demonstration of Custom Elicitation Handler
|
|
4
|
+
|
|
5
|
+
This example demonstrates a custom elicitation handler that creates
|
|
6
|
+
an interactive game character creation experience with dice rolls,
|
|
7
|
+
visual gauges, and fun interactions.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
|
|
12
|
+
# Import our custom handler from the separate module
|
|
13
|
+
from game_character_handler import game_character_elicitation_handler
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
|
|
17
|
+
from fast_agent import FastAgent
|
|
18
|
+
from fast_agent.mcp.helpers.content_helpers import get_resource_text
|
|
19
|
+
|
|
20
|
+
fast = FastAgent("Game Character Creator", quiet=True)
|
|
21
|
+
console = Console()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@fast.agent(
|
|
25
|
+
"character-creator",
|
|
26
|
+
servers=["elicitation_game_server"],
|
|
27
|
+
# Register our handler from game_character_handler.py
|
|
28
|
+
elicitation_handler=game_character_elicitation_handler,
|
|
29
|
+
)
|
|
30
|
+
async def main():
|
|
31
|
+
"""Run the game character creator with custom elicitation handler."""
|
|
32
|
+
async with fast.run() as agent:
|
|
33
|
+
console.print(
|
|
34
|
+
Panel(
|
|
35
|
+
"[bold cyan]Welcome to the Character Creation Studio![/bold cyan]\n\n"
|
|
36
|
+
"Create your hero with our magical character generator.\n"
|
|
37
|
+
"Watch as the cosmic dice determine your fate!",
|
|
38
|
+
title="🎮 Game Time 🎮",
|
|
39
|
+
border_style="magenta",
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Trigger the character creation
|
|
44
|
+
result = await agent.get_resource("elicitation://game-character")
|
|
45
|
+
|
|
46
|
+
if result_text := get_resource_text(result):
|
|
47
|
+
character_panel = Panel(
|
|
48
|
+
result_text, title="📜 Your Character 📜", border_style="green", expand=False
|
|
49
|
+
)
|
|
50
|
+
console.print(character_panel)
|
|
51
|
+
|
|
52
|
+
console.print("\n[italic]Your character is ready for adventure![/italic]")
|
|
53
|
+
console.print("[dim]The tavern door opens, and your journey begins...[/dim]\n")
|
|
54
|
+
|
|
55
|
+
# Fun ending based on character
|
|
56
|
+
if "Powerful character" in result_text:
|
|
57
|
+
console.print("⚔️ [bold]The realm trembles at your might![/bold]")
|
|
58
|
+
elif "Challenging build" in result_text:
|
|
59
|
+
console.print("🎯 [bold]True heroes are forged through adversity![/bold]")
|
|
60
|
+
else:
|
|
61
|
+
console.print("🗡️ [bold]Your legend begins now![/bold]")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if __name__ == "__main__":
|
|
65
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom Elicitation Handler for Game Character Creation
|
|
3
|
+
|
|
4
|
+
This module provides a whimsical custom elicitation handler that creates
|
|
5
|
+
an interactive game character creation experience with dice rolls,
|
|
6
|
+
visual gauges, and animated effects.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import random
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
|
|
13
|
+
from mcp.shared.context import RequestContext
|
|
14
|
+
from mcp.types import ElicitRequestParams, ElicitResult
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
from rich.progress import BarColumn, Progress, TextColumn
|
|
17
|
+
from rich.prompt import Confirm
|
|
18
|
+
from rich.table import Table
|
|
19
|
+
|
|
20
|
+
from fast_agent.core.logging.logger import get_logger
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from mcp import ClientSession
|
|
24
|
+
|
|
25
|
+
logger = get_logger(__name__)
|
|
26
|
+
console = Console()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def game_character_elicitation_handler(
|
|
30
|
+
context: RequestContext["ClientSession", Any],
|
|
31
|
+
params: ElicitRequestParams,
|
|
32
|
+
) -> ElicitResult:
|
|
33
|
+
"""Custom handler that creates an interactive character creation experience."""
|
|
34
|
+
logger.info(f"Game character elicitation handler called: {params.message}")
|
|
35
|
+
|
|
36
|
+
if params.requestedSchema:
|
|
37
|
+
properties = params.requestedSchema.get("properties", {})
|
|
38
|
+
content: dict[str, Any] = {}
|
|
39
|
+
|
|
40
|
+
console.print("\n[bold magenta]🎮 Character Creation Studio 🎮[/bold magenta]\n")
|
|
41
|
+
|
|
42
|
+
# Character name with typewriter effect
|
|
43
|
+
if "character_name" in properties:
|
|
44
|
+
console.print("[cyan]✨ Generating your character's name...[/cyan] ", end="")
|
|
45
|
+
name_prefixes = ["Hero", "Legend", "Epic", "Mighty", "Brave", "Noble"]
|
|
46
|
+
name_suffixes = ["blade", "heart", "storm", "fire", "shadow", "star"]
|
|
47
|
+
|
|
48
|
+
name = f"{random.choice(name_prefixes)}{random.choice(name_suffixes)}{random.randint(1, 999)}"
|
|
49
|
+
|
|
50
|
+
for char in name:
|
|
51
|
+
console.print(char, end="", style="bold green")
|
|
52
|
+
await asyncio.sleep(0.03)
|
|
53
|
+
console.print("\n")
|
|
54
|
+
content["character_name"] = name
|
|
55
|
+
|
|
56
|
+
# Class selection with visual menu and fate dice
|
|
57
|
+
if "character_class" in properties:
|
|
58
|
+
class_enum = properties["character_class"].get("enum", [])
|
|
59
|
+
class_names = properties["character_class"].get("enumNames", class_enum)
|
|
60
|
+
|
|
61
|
+
table = Table(title="🎯 Choose Your Destiny", show_header=False, box=None)
|
|
62
|
+
table.add_column("Option", style="cyan", width=8)
|
|
63
|
+
table.add_column("Class", style="yellow", width=20)
|
|
64
|
+
table.add_column("Description", style="dim", width=30)
|
|
65
|
+
|
|
66
|
+
descriptions = [
|
|
67
|
+
"Master of sword and shield",
|
|
68
|
+
"Wielder of arcane mysteries",
|
|
69
|
+
"Silent shadow striker",
|
|
70
|
+
"Nature's deadly archer",
|
|
71
|
+
"Holy warrior of light",
|
|
72
|
+
"Inspiring magical performer",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
for i, (cls, name, desc) in enumerate(zip(class_enum, class_names, descriptions)):
|
|
76
|
+
table.add_row(f"[{i + 1}]", name, desc)
|
|
77
|
+
|
|
78
|
+
console.print(table)
|
|
79
|
+
|
|
80
|
+
# Dramatic fate dice roll
|
|
81
|
+
console.print("\n[bold yellow]🎲 The Fates decide your path...[/bold yellow]")
|
|
82
|
+
for _ in range(8):
|
|
83
|
+
dice_face = random.choice(["⚀", "⚁", "⚂", "⚃", "⚄", "⚅"])
|
|
84
|
+
console.print(f"\r Rolling... {dice_face}", end="")
|
|
85
|
+
await asyncio.sleep(0.2)
|
|
86
|
+
|
|
87
|
+
fate_roll = random.randint(1, 6)
|
|
88
|
+
selected_idx = (fate_roll - 1) % len(class_enum)
|
|
89
|
+
console.print(f"\n 🎲 Fate dice: [bold red]{fate_roll}[/bold red]!")
|
|
90
|
+
console.print(
|
|
91
|
+
f"✨ Destiny has chosen: [bold yellow]{class_names[selected_idx]}[/bold yellow]!\n"
|
|
92
|
+
)
|
|
93
|
+
content["character_class"] = class_enum[selected_idx]
|
|
94
|
+
|
|
95
|
+
# Stats rolling with animated progress bars and cosmic effects
|
|
96
|
+
stat_names = ["strength", "intelligence", "dexterity", "charisma"]
|
|
97
|
+
stats_info = {
|
|
98
|
+
"strength": {"emoji": "💪", "desc": "Physical power"},
|
|
99
|
+
"intelligence": {"emoji": "🧠", "desc": "Mental acuity"},
|
|
100
|
+
"dexterity": {"emoji": "🏃", "desc": "Agility & speed"},
|
|
101
|
+
"charisma": {"emoji": "✨", "desc": "Personal magnetism"},
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.print("[bold]🌟 Rolling cosmic dice for your abilities...[/bold]\n")
|
|
105
|
+
|
|
106
|
+
with Progress(
|
|
107
|
+
TextColumn("[progress.description]{task.description}"),
|
|
108
|
+
BarColumn(bar_width=25, style="cyan", complete_style="green"),
|
|
109
|
+
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
|
110
|
+
console=console,
|
|
111
|
+
) as progress:
|
|
112
|
+
for stat in stat_names:
|
|
113
|
+
if stat in properties:
|
|
114
|
+
# Roll 3d6 for classic D&D feel with bonus potential
|
|
115
|
+
rolls = [random.randint(1, 6) for _ in range(3)]
|
|
116
|
+
total = sum(rolls)
|
|
117
|
+
|
|
118
|
+
# Add cosmic bonus chance
|
|
119
|
+
if random.random() < 0.15: # 15% chance for cosmic boost
|
|
120
|
+
cosmic_bonus = random.randint(1, 3)
|
|
121
|
+
total = min(18, total + cosmic_bonus)
|
|
122
|
+
cosmic_text = f" ✨+{cosmic_bonus} COSMIC✨"
|
|
123
|
+
else:
|
|
124
|
+
cosmic_text = ""
|
|
125
|
+
|
|
126
|
+
stat_info = stats_info.get(stat, {"emoji": "📊", "desc": stat.title()})
|
|
127
|
+
task = progress.add_task(
|
|
128
|
+
f"{stat_info['emoji']} {stat.capitalize()}: {stat_info['desc']}", total=18
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Animate the progress bar with suspense
|
|
132
|
+
for i in range(total + 1):
|
|
133
|
+
progress.update(task, completed=i)
|
|
134
|
+
await asyncio.sleep(0.04)
|
|
135
|
+
|
|
136
|
+
content[stat] = total
|
|
137
|
+
console.print(
|
|
138
|
+
f" 🎲 Rolled: {rolls} = [bold green]{total}[/bold green]{cosmic_text}"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Lucky dice legendary challenge
|
|
142
|
+
if "lucky_dice" in properties:
|
|
143
|
+
console.print("\n" + "=" * 60)
|
|
144
|
+
console.print("[bold yellow]🎰 LEGENDARY CHALLENGE: Lucky Dice! 🎰[/bold yellow]")
|
|
145
|
+
console.print("The ancient dice of fortune whisper your name...")
|
|
146
|
+
console.print("Do you dare tempt fate for legendary power?")
|
|
147
|
+
console.print("=" * 60)
|
|
148
|
+
|
|
149
|
+
# Epic dice rolling sequence
|
|
150
|
+
console.print("\n[cyan]🌟 Rolling the Dice of Destiny...[/cyan]")
|
|
151
|
+
|
|
152
|
+
for i in range(15):
|
|
153
|
+
dice_faces = ["⚀", "⚁", "⚂", "⚃", "⚄", "⚅"]
|
|
154
|
+
d20_faces = ["🎲"] * 19 + ["💎"] # Special diamond for 20
|
|
155
|
+
|
|
156
|
+
if i < 10:
|
|
157
|
+
face = random.choice(dice_faces)
|
|
158
|
+
else:
|
|
159
|
+
face = random.choice(d20_faces)
|
|
160
|
+
|
|
161
|
+
console.print(f"\r [bold]{face}[/bold] Rolling...", end="")
|
|
162
|
+
await asyncio.sleep(0.15)
|
|
163
|
+
|
|
164
|
+
final_roll = random.randint(1, 20)
|
|
165
|
+
|
|
166
|
+
if final_roll == 20:
|
|
167
|
+
console.print("\r [bold red]💎 NATURAL 20! 💎[/bold red]")
|
|
168
|
+
console.print(" [bold green]🌟 LEGENDARY SUCCESS! 🌟[/bold green]")
|
|
169
|
+
console.print(" [gold1]You have been blessed by the gods themselves![/gold1]")
|
|
170
|
+
bonus_text = "🏆 Divine Champion status unlocked!"
|
|
171
|
+
elif final_roll >= 18:
|
|
172
|
+
console.print(f"\r [bold yellow]⭐ {final_roll} - EPIC ROLL! ⭐[/bold yellow]")
|
|
173
|
+
bonus_text = "🎁 Epic treasure discovered!"
|
|
174
|
+
elif final_roll >= 15:
|
|
175
|
+
console.print(f"\r [green]🎲 {final_roll} - Great success![/green]")
|
|
176
|
+
bonus_text = "🌟 Rare magical item found!"
|
|
177
|
+
elif final_roll >= 10:
|
|
178
|
+
console.print(f"\r [yellow]🎲 {final_roll} - Good fortune.[/yellow]")
|
|
179
|
+
bonus_text = "🗡️ Modest blessing received."
|
|
180
|
+
elif final_roll == 1:
|
|
181
|
+
console.print("\r [bold red]💀 CRITICAL FUMBLE! 💀[/bold red]")
|
|
182
|
+
bonus_text = "😅 Learning experience gained... try again!"
|
|
183
|
+
else:
|
|
184
|
+
console.print(f"\r [dim]🎲 {final_roll} - The dice are silent.[/dim]")
|
|
185
|
+
bonus_text = "🎯 Your destiny remains unwritten."
|
|
186
|
+
|
|
187
|
+
console.print(f" [italic]{bonus_text}[/italic]")
|
|
188
|
+
content["lucky_dice"] = final_roll >= 10
|
|
189
|
+
|
|
190
|
+
# Epic character summary with theatrical flair
|
|
191
|
+
console.print("\n" + "=" * 70)
|
|
192
|
+
console.print("[bold cyan]📜 Your Character Has Been Rolled! 📜[/bold cyan]")
|
|
193
|
+
console.print("=" * 70)
|
|
194
|
+
|
|
195
|
+
# Show character summary
|
|
196
|
+
total_stats = sum(content.get(stat, 10) for stat in stat_names if stat in content)
|
|
197
|
+
|
|
198
|
+
# Create a simple table
|
|
199
|
+
stats_table = Table(show_header=False, box=None)
|
|
200
|
+
stats_table.add_column("Label", style="cyan", width=15)
|
|
201
|
+
stats_table.add_column("Value", style="bold white")
|
|
202
|
+
|
|
203
|
+
if "character_name" in content:
|
|
204
|
+
stats_table.add_row("Name:", content["character_name"])
|
|
205
|
+
if "character_class" in content:
|
|
206
|
+
class_idx = class_enum.index(content["character_class"])
|
|
207
|
+
stats_table.add_row("Class:", class_names[class_idx])
|
|
208
|
+
|
|
209
|
+
stats_table.add_row("", "") # Empty row for spacing
|
|
210
|
+
|
|
211
|
+
# Add stats
|
|
212
|
+
for stat in stat_names:
|
|
213
|
+
if stat in content:
|
|
214
|
+
stat_label = f"{stat.capitalize()}:"
|
|
215
|
+
stats_table.add_row(stat_label, str(content[stat]))
|
|
216
|
+
|
|
217
|
+
stats_table.add_row("", "")
|
|
218
|
+
stats_table.add_row("Total Power:", str(total_stats))
|
|
219
|
+
|
|
220
|
+
console.print(stats_table)
|
|
221
|
+
|
|
222
|
+
# Power message
|
|
223
|
+
if total_stats > 60:
|
|
224
|
+
console.print("✨ [bold gold1]The realm trembles before your might![/bold gold1] ✨")
|
|
225
|
+
elif total_stats > 50:
|
|
226
|
+
console.print("⚔️ [bold green]A formidable hero rises![/bold green] ⚔️")
|
|
227
|
+
elif total_stats < 35:
|
|
228
|
+
console.print("🎯 [bold blue]The underdog's tale begins![/bold blue] 🎯")
|
|
229
|
+
else:
|
|
230
|
+
console.print("🗡️ [bold white]Adventure awaits the worthy![/bold white] 🗡️")
|
|
231
|
+
|
|
232
|
+
# Ask for confirmation
|
|
233
|
+
console.print("\n[bold yellow]Do you accept this character?[/bold yellow]")
|
|
234
|
+
console.print("[dim]Press Enter to accept, 'n' to decline, or Ctrl+C to cancel[/dim]\n")
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
accepted = Confirm.ask("Accept character?", default=True)
|
|
238
|
+
|
|
239
|
+
if accepted:
|
|
240
|
+
console.print(
|
|
241
|
+
"\n[bold green]✅ Character accepted! Your adventure begins![/bold green]"
|
|
242
|
+
)
|
|
243
|
+
return ElicitResult(action="accept", content=content)
|
|
244
|
+
else:
|
|
245
|
+
console.print(
|
|
246
|
+
"\n[yellow]❌ Character declined. The fates will roll again...[/yellow]"
|
|
247
|
+
)
|
|
248
|
+
return ElicitResult(action="decline")
|
|
249
|
+
except KeyboardInterrupt:
|
|
250
|
+
console.print("\n[red]❌ Character creation cancelled![/red]")
|
|
251
|
+
return ElicitResult(action="cancel")
|
|
252
|
+
|
|
253
|
+
else:
|
|
254
|
+
# No schema, return a fun message
|
|
255
|
+
content = {"response": "⚔️ Ready for adventure! ⚔️"}
|
|
256
|
+
return ElicitResult(action="accept", content=content)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from fast_agent import FastAgent
|
|
4
|
+
|
|
5
|
+
# Create the application
|
|
6
|
+
fast = FastAgent("fast-agent example")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Define the agent
|
|
10
|
+
@fast.agent(
|
|
11
|
+
instruction="You are a helpful AI Agent",
|
|
12
|
+
servers=["elicitation_account_server"],
|
|
13
|
+
)
|
|
14
|
+
async def main():
|
|
15
|
+
# use the --model command line switch or agent arguments to change model
|
|
16
|
+
async with fast.run() as agent:
|
|
17
|
+
await agent.send('***CALL_TOOL create_user_account {"service_name": "fast-agent"}')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from fast_agent import FastAgent
|
|
4
|
+
|
|
5
|
+
# Create the application
|
|
6
|
+
fast = FastAgent("fast-agent agent_one (mcp server)")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Define the agent
|
|
10
|
+
@fast.agent(name="agent_one", instruction="You are a helpful AI Agent.")
|
|
11
|
+
async def main():
|
|
12
|
+
# use the --model command line switch or agent arguments to change model
|
|
13
|
+
async with fast.run() as agent:
|
|
14
|
+
await agent.interactive()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from fast_agent import FastAgent
|
|
4
|
+
|
|
5
|
+
# Create the application
|
|
6
|
+
fast = FastAgent("fast-agent agent_two (mcp client)")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Define the agent
|
|
10
|
+
@fast.agent(name="agent_two", instruction="You are a helpful AI Agent.", servers=["agent_one"])
|
|
11
|
+
async def main():
|
|
12
|
+
# use the --model command line switch or agent arguments to change model
|
|
13
|
+
async with fast.run() as agent:
|
|
14
|
+
await agent.interactive()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Model string takes format:
|
|
2
|
+
# <provider>.<model_string>.<reasoning_effort?> (e.g. anthropic.claude-3-5-sonnet-20241022 or openai.o3-mini.low)
|
|
3
|
+
#
|
|
4
|
+
# Can be overriden with a command line switch --model=<model>, or within the Agent decorator.
|
|
5
|
+
# Check here for current details: https://fast-agent.ai/models/
|
|
6
|
+
|
|
7
|
+
# set the default model for fast-agent below:
|
|
8
|
+
default_model: gpt-4.1
|
|
9
|
+
|
|
10
|
+
# Logging and Console Configuration:
|
|
11
|
+
logger:
|
|
12
|
+
# Switched off to avoid polluting the console
|
|
13
|
+
progress_display: false
|
|
14
|
+
|
|
15
|
+
# Show chat User/Assistant messages on the console
|
|
16
|
+
show_chat: true
|
|
17
|
+
# Show tool calls on the console
|
|
18
|
+
show_tools: true
|
|
19
|
+
# Truncate long tool responses on the console
|
|
20
|
+
truncate_tools: true
|
|
21
|
+
|
|
22
|
+
# MCP Servers
|
|
23
|
+
mcp:
|
|
24
|
+
servers:
|
|
25
|
+
agent_one:
|
|
26
|
+
transport: http
|
|
27
|
+
url: http://localhost:8001/mcp
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# FastAgent Secrets Configuration
|
|
2
|
+
# WARNING: Keep this file secure and never commit to version control
|
|
3
|
+
|
|
4
|
+
# Alternatively set OPENAI_API_KEY, ANTHROPIC_API_KEY or other environment variables.
|
|
5
|
+
# Keys in the configuration file override environment variables.
|
|
6
|
+
|
|
7
|
+
openai:
|
|
8
|
+
api_key: <your-api-key-here>
|
|
9
|
+
anthropic:
|
|
10
|
+
api_key: <your-api-key-here>
|
|
11
|
+
deepseek:
|
|
12
|
+
api_key: <your-api-key-here>
|
|
13
|
+
openrouter:
|
|
14
|
+
api_key: <your-api-key-here>
|
|
15
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Please edit this configuration file to match your environment (on Windows).
|
|
3
|
+
# Examples in comments below - check/change the paths.
|
|
4
|
+
#
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
logger:
|
|
8
|
+
type: console
|
|
9
|
+
level: error
|
|
10
|
+
truncate_tools: true
|
|
11
|
+
|
|
12
|
+
mcp:
|
|
13
|
+
servers:
|
|
14
|
+
brave:
|
|
15
|
+
# On windows replace the command and args line to use `node` and the absolute path to the server.
|
|
16
|
+
# Use `npm i -g @modelcontextprotocol/server-brave-search` to install the server globally.
|
|
17
|
+
# Use `npm -g root` to find the global node_modules path.`
|
|
18
|
+
# command: "node"
|
|
19
|
+
# args: ["c:/Program Files/nodejs/node_modules/@modelcontextprotocol/server-brave-search/dist/index.js"]
|
|
20
|
+
command: "npx"
|
|
21
|
+
args: ["-y", "@modelcontextprotocol/server-brave-search"]
|
|
22
|
+
env:
|
|
23
|
+
# You can also place your BRAVE_API_KEY in the fastagent.secrets.yaml file.
|
|
24
|
+
BRAVE_API_KEY: <your_brave_api_key>
|
|
25
|
+
filesystem:
|
|
26
|
+
# On windows update the command and arguments to use `node` and the absolute path to the server.
|
|
27
|
+
# Use `npm i -g @modelcontextprotocol/server-filesystem` to install the server globally.
|
|
28
|
+
# Use `npm -g root` to find the global node_modules path.`
|
|
29
|
+
# command: "node"
|
|
30
|
+
# args: ["c:/Program Files/nodejs/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js","./agent_folder"]
|
|
31
|
+
command: "npx"
|
|
32
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "./agent_folder/"]
|
|
33
|
+
interpreter:
|
|
34
|
+
command: "docker"
|
|
35
|
+
args: [
|
|
36
|
+
"run",
|
|
37
|
+
"-i",
|
|
38
|
+
"--rm",
|
|
39
|
+
"--pull=always",
|
|
40
|
+
"-v",
|
|
41
|
+
"./agent_folder:/mnt/data/",
|
|
42
|
+
# Docker needs the absolute path on Windows (e.g. "x:/fastagent/agent_folder:/mnt/data/")
|
|
43
|
+
# "./agent_folder:/mnt/data/",
|
|
44
|
+
"ghcr.io/evalstate/mcp-py-repl:latest",
|
|
45
|
+
]
|
|
46
|
+
roots:
|
|
47
|
+
- uri: "file://./agent_folder/"
|
|
48
|
+
name: "agent_folder"
|
|
49
|
+
server_uri_alias: "file:///mnt/data/"
|
|
50
|
+
fetch:
|
|
51
|
+
command: "uvx"
|
|
52
|
+
args: ["mcp-server-fetch"]
|
|
53
|
+
sequential:
|
|
54
|
+
command: "npx"
|
|
55
|
+
args: ["-y", "@modelcontextprotocol/server-sequential-thinking"]
|
|
56
|
+
# webmcp:
|
|
57
|
+
# command: "node"
|
|
58
|
+
# args: ["/home/ssmith/.webmcp/server.cjs"]
|
|
59
|
+
# env:
|
|
60
|
+
# WEBMCP_SERVER_TOKEN: 96e22896d8143fc1d61fec09208fc5ed
|
|
61
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from fast_agent import FastAgent
|
|
4
|
+
|
|
5
|
+
agents = FastAgent(name="Researcher Agent (EO)")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@agents.agent(
|
|
9
|
+
name="Researcher",
|
|
10
|
+
instruction="""
|
|
11
|
+
You are a research assistant, with access to internet search (via Brave),
|
|
12
|
+
website fetch, a python interpreter (you can install packages with uv) and a filesystem.
|
|
13
|
+
Use the current working directory to save and create files with both the Interpreter and Filesystem tools.
|
|
14
|
+
The interpreter has numpy, pandas, matplotlib and seaborn already installed.
|
|
15
|
+
|
|
16
|
+
You must always provide a summary of the specific sources you have used in your research.
|
|
17
|
+
""",
|
|
18
|
+
servers=["brave", "interpreter", "filesystem", "fetch"],
|
|
19
|
+
)
|
|
20
|
+
@agents.agent(
|
|
21
|
+
name="Evaluator",
|
|
22
|
+
model="sonnet",
|
|
23
|
+
instruction="""
|
|
24
|
+
Evaluate the response from the researcher based on the criteria:
|
|
25
|
+
- Sources cited. Has the researcher provided a summary of the specific sources used in the research?
|
|
26
|
+
- Validity. Has the researcher cross-checked and validated data and assumptions.
|
|
27
|
+
- Alignment. Has the researher acted and addressed feedback from any previous assessments?
|
|
28
|
+
|
|
29
|
+
For each criterion:
|
|
30
|
+
- Provide a rating (EXCELLENT, GOOD, FAIR, or POOR).
|
|
31
|
+
- Offer specific feedback or suggestions for improvement.
|
|
32
|
+
|
|
33
|
+
Summarize your evaluation as a structured response with:
|
|
34
|
+
- Overall quality rating.
|
|
35
|
+
- Specific feedback and areas for improvement.""",
|
|
36
|
+
)
|
|
37
|
+
@agents.evaluator_optimizer(
|
|
38
|
+
generator="Researcher",
|
|
39
|
+
evaluator="Evaluator",
|
|
40
|
+
max_refinements=5,
|
|
41
|
+
min_rating="EXCELLENT",
|
|
42
|
+
name="Researcher_Evaluator",
|
|
43
|
+
)
|
|
44
|
+
async def main() -> None:
|
|
45
|
+
async with agents.run() as agent:
|
|
46
|
+
await agent.prompt("Researcher_Evaluator")
|
|
47
|
+
|
|
48
|
+
print("Ask follow up quesions to the Researcher?")
|
|
49
|
+
await agent.prompt("Researcher", default_prompt="STOP")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
asyncio.run(main())
|