fast-agent-mcp 0.0.15__tar.gz → 0.0.16__tar.gz
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_mcp-0.0.15 → fast_agent_mcp-0.0.16}/PKG-INFO +116 -17
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/README.md +115 -16
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/pyproject.toml +1 -1
- fast_agent_mcp-0.0.16/src/mcp_agent/cli/__main__.py +7 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/config.py +19 -11
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/enhanced_prompt.py +10 -2
- fast_agent_mcp-0.0.16/src/mcp_agent/resources/examples/data-analysis/analysis.py +61 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/evaluator.py +0 -2
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/parallel.py +0 -4
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +112 -31
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/augmented_llm_anthropic.py +16 -2
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/augmented_llm_openai.py +13 -1
- fast_agent_mcp-0.0.16/src/mcp_agent/workflows/llm/prompt_utils.py +137 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/orchestrator/orchestrator.py +206 -52
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/orchestrator/orchestrator_models.py +81 -9
- fast_agent_mcp-0.0.16/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +188 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/router_base.py +113 -21
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/router_llm.py +19 -5
- fast_agent_mcp-0.0.15/src/mcp_agent/cli/__main__.py +0 -4
- fast_agent_mcp-0.0.15/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -35
- fast_agent_mcp-0.0.15/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +0 -118
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/.gitignore +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/LICENSE +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/agents/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/agents/agent.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/app.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/commands/bootstrap.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/commands/config.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/commands/setup.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/main.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/cli/terminal.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/console.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/context.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/context_dependent.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/agent_app.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/agent_types.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/agent_utils.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/error_handling.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/exceptions.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/fastagent.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/proxies.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/server_validation.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/core/types.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/eval/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/event_progress.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/decorator_registry.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/executor.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/task_registry.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/temporal.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/workflow.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/executor/workflow_signal.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/human_input/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/human_input/handler.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/human_input/types.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/events.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/json_serializer.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/listeners.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/logger.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/rich_progress.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/tracing.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/logging/transport.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/gen_client.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/mcp_activity.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/mcp_agent_client_session.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/mcp_agent_server.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/mcp_aggregator.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/mcp_connection_manager.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp/stdio.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/mcp_server_registry.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/progress_display.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/internal/job.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/internal/social.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/agent_build.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/orchestrator.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/telemetry/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/telemetry/usage_tracking.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/embedding/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/embedding/embedding_base.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/embedding/embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/embedding/embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/augmented_llm.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/llm_selector.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/llm/model_factory.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/orchestrator/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/parallel/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/parallel/fan_in.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/parallel/fan_out.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/parallel/parallel_llm.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/router_embedding.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/router_embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/router/router_embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/swarm/__init__.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/swarm/swarm.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/swarm/swarm_anthropic.py +0 -0
- {fast_agent_mcp-0.0.15 → fast_agent_mcp-0.0.16}/src/mcp_agent/workflows/swarm/swarm_openai.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fast-agent-mcp
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.16
|
4
4
|
Summary: Define, Prompt and Test MCP enabled Agents and Workflows
|
5
5
|
Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
|
6
6
|
License: Apache License
|
@@ -259,14 +259,17 @@ Prompts and configurations that define your Agent Applications are stored in sim
|
|
259
259
|
|
260
260
|
Chat with individual Agents and Components before, during and after workflow execution to tune and diagnose your application.
|
261
261
|
|
262
|
-
Simple model selection makes testing Model <-> MCP Server interaction painless.
|
262
|
+
Simple model selection makes testing Model <-> MCP Server interaction painless. You can read more about the motivation behind this project [here](https://llmindset.co.uk/resources/fast-agent/)
|
263
|
+
|
264
|
+

|
263
265
|
|
264
266
|
## Get started:
|
265
267
|
|
266
268
|
Start by installing the [uv package manager](https://docs.astral.sh/uv/) for Python. Then:
|
267
269
|
|
268
270
|
```bash
|
269
|
-
uv pip install fast-agent-mcp # install fast-agent
|
271
|
+
uv pip install fast-agent-mcp # install fast-agent!
|
272
|
+
|
270
273
|
fast-agent setup # create an example agent and config files
|
271
274
|
uv run agent.py # run your first agent
|
272
275
|
uv run agent.py --model=o3-mini.low # specify a model
|
@@ -275,6 +278,7 @@ fast-agent bootstrap workflow # create "building effective agents" example
|
|
275
278
|
|
276
279
|
Other bootstrap examples include a Researcher Agent (with Evaluator-Optimizer workflow) and Data Analysis Agent (similar to the ChatGPT experience), demonstrating MCP Roots support.
|
277
280
|
|
281
|
+
> [!TIP]
|
278
282
|
> Windows Users - there are a couple of configuration changes needed for the Filesystem and Docker MCP Servers - necessary changes are detailed within the configuration files.
|
279
283
|
|
280
284
|
### Basic Agents
|
@@ -354,7 +358,7 @@ async def main():
|
|
354
358
|
)
|
355
359
|
```
|
356
360
|
|
357
|
-
All Agents and Workflows respond to `.send("message")`
|
361
|
+
All Agents and Workflows respond to `.send("message")` or `.prompt()` to begin a chat session.
|
358
362
|
|
359
363
|
Saved as `social.py` we can now run this workflow from the command line with:
|
360
364
|
|
@@ -362,7 +366,7 @@ Saved as `social.py` we can now run this workflow from the command line with:
|
|
362
366
|
uv run social.py --agent social_media --message "<url>"
|
363
367
|
```
|
364
368
|
|
365
|
-
Add the `--quiet` switch to only return the final response.
|
369
|
+
Add the `--quiet` switch to only return the final response, which is useful for simple automations.
|
366
370
|
|
367
371
|
## Workflows
|
368
372
|
|
@@ -383,7 +387,7 @@ async with fast.run() as agent:
|
|
383
387
|
|
384
388
|
```
|
385
389
|
|
386
|
-
This starts an interactive session, which produces a short social media post for a given URL. If a _chain_ is prompted
|
390
|
+
This starts an interactive session, which produces a short social media post for a given URL. If a _chain_ is prompted it returns to a chat with last Agent in the chain. You can switch the agent to prompt by typing `@agent-name`.
|
387
391
|
|
388
392
|
Chains can be incorporated in other workflows, or contain other workflow elements (including other Chains). You can set an `instruction` to precisely describe it's capabilities to other workflow steps if needed.
|
389
393
|
|
@@ -407,9 +411,9 @@ The Parallel Workflow sends the same message to multiple Agents simultaneously (
|
|
407
411
|
)
|
408
412
|
```
|
409
413
|
|
410
|
-
Look at the `parallel.py` workflow example for more examples. If you don't specify a `fan-in` agent, the `parallel` returns Agent results verbatim.
|
414
|
+
Look at the `parallel.py` workflow example for more examples. If you don't specify a `fan-in` agent, the `parallel` returns the combined Agent results verbatim.
|
411
415
|
|
412
|
-
|
416
|
+
`parallel` is also useful to ensemble ideas from different LLMs.
|
413
417
|
|
414
418
|
### Evaluator-Optimizer
|
415
419
|
|
@@ -458,20 +462,107 @@ See `orchestrator.py` in the workflow examples.
|
|
458
462
|
|
459
463
|
## Agent Features
|
460
464
|
|
465
|
+
### Calling Agents
|
466
|
+
|
467
|
+
All definitions allow omitting the name and instructions arguments for brevity:
|
468
|
+
|
469
|
+
```python
|
470
|
+
@fast.agent("You are a helpful agent") # Create an agent with a default name.
|
471
|
+
@fast.agent("greeter","Respond cheerfully!") # Create an agent with the name "greeter"
|
472
|
+
|
473
|
+
moon_size = await agent("the moon") # Call the default (first defined agent) with a message
|
474
|
+
|
475
|
+
result = await agent.greeter("Good morning!") # Send a message to an agent by name using dot notation
|
476
|
+
result = await agent.greeter.send("Hello!") # You can call 'send' explicitly
|
477
|
+
|
478
|
+
await agent.greeter() # If no message is specified, a chat session will open
|
479
|
+
await agent.greeter.prompt() # that can be made more explicit
|
480
|
+
await agent.greeter.prompt(default_prompt="OK") # and supports setting a default prompt
|
481
|
+
|
482
|
+
agent["greeter"].send("Good Evening!") # Dictionary access is supported if preferred
|
483
|
+
```
|
484
|
+
|
485
|
+
### Defining Agents
|
486
|
+
|
487
|
+
#### Basic Agent
|
488
|
+
|
461
489
|
```python
|
462
490
|
@fast.agent(
|
463
|
-
name="agent",
|
464
|
-
|
465
|
-
servers=["filesystem"],
|
466
|
-
model="o3-mini.high",
|
467
|
-
use_history=True,
|
468
|
-
|
491
|
+
name="agent", # name of the agent
|
492
|
+
instruction="You are a helpful Agent", # base instruction for the agent
|
493
|
+
servers=["filesystem"], # list of MCP Servers for the agent
|
494
|
+
model="o3-mini.high", # specify a model for the agent
|
495
|
+
use_history=True, # agent maintains chat history
|
496
|
+
request_params={"temperature": 0.7}, # additional parameters for the LLM (or RequestParams())
|
497
|
+
human_input=True, # agent can request human input
|
498
|
+
)
|
499
|
+
```
|
500
|
+
|
501
|
+
#### Chain
|
502
|
+
|
503
|
+
```python
|
504
|
+
@fast.chain(
|
505
|
+
name="chain", # name of the chain
|
506
|
+
sequence=["agent1", "agent2", ...], # list of agents in execution order
|
507
|
+
instruction="instruction", # instruction to describe the chain for other workflows
|
508
|
+
continue_with_final=True, # open chat with agent at end of chain after prompting
|
469
509
|
)
|
470
510
|
```
|
471
511
|
|
472
|
-
|
512
|
+
#### Parallel
|
513
|
+
|
514
|
+
```python
|
515
|
+
@fast.parallel(
|
516
|
+
name="parallel", # name of the parallel workflow
|
517
|
+
fan_out=["agent1", "agent2"], # list of agents to run in parallel
|
518
|
+
fan_in="aggregator", # name of agent that combines results (optional)
|
519
|
+
instruction="instruction", # instruction to describe the parallel for other workflows
|
520
|
+
include_request=True, # include original request in fan-in message
|
521
|
+
)
|
522
|
+
```
|
473
523
|
|
474
|
-
|
524
|
+
#### Evaluator-Optimizer
|
525
|
+
|
526
|
+
```python
|
527
|
+
@fast.evaluator_optimizer(
|
528
|
+
name="researcher", # name of the workflow
|
529
|
+
generator="web_searcher", # name of the content generator agent
|
530
|
+
evaluator="quality_assurance", # name of the evaluator agent
|
531
|
+
min_rating="GOOD", # minimum acceptable quality (EXCELLENT, GOOD, FAIR, POOR)
|
532
|
+
max_refinements=3, # maximum number of refinement iterations
|
533
|
+
)
|
534
|
+
```
|
535
|
+
|
536
|
+
#### Router
|
537
|
+
|
538
|
+
```python
|
539
|
+
@fast.router(
|
540
|
+
name="route", # name of the router
|
541
|
+
agents=["agent1", "agent2", "agent3"], # list of agent names router can delegate to
|
542
|
+
model="o3-mini.high", # specify routing model
|
543
|
+
use_history=True, # router maintains chat history
|
544
|
+
human_input=False, # whether router can request human input
|
545
|
+
)
|
546
|
+
```
|
547
|
+
|
548
|
+
#### Orchestrator
|
549
|
+
|
550
|
+
```python
|
551
|
+
@fast.orchestrator(
|
552
|
+
name="orchestrator", # name of the orchestrator
|
553
|
+
instruction="instruction", # base instruction for the orchestrator
|
554
|
+
agents=["agent1", "agent2"], # list of agent names this orchestrator can use
|
555
|
+
model="o3-mini.high", # specify orchestrator planning model
|
556
|
+
use_history=False, # orchestrator doesn't maintain chat history by default
|
557
|
+
human_input=False, # whether orchestrator can request human input
|
558
|
+
plan_type="full", # planning approach: "full" or "iterative"
|
559
|
+
)
|
560
|
+
```
|
561
|
+
|
562
|
+
### Secrets File
|
563
|
+
|
564
|
+
> [!TIP]
|
565
|
+
> fast-agent will look recursively for a fastagent.secrets.yaml file, so you only need to manage this at the root folder of your agent definitions.
|
475
566
|
|
476
567
|
## Project Notes
|
477
568
|
|
@@ -479,8 +570,11 @@ When `human_input` is set to true for an Agent, it is presented with the option
|
|
479
570
|
|
480
571
|
### llmindset.co.uk fork:
|
481
572
|
|
573
|
+
- Remove instructor use for Orchestrator
|
574
|
+
- Improved handling of Parallel/Fan-In and respose option
|
575
|
+
- XML based generated prompts
|
482
576
|
- "FastAgent" style prototyping, with per-agent models
|
483
|
-
-
|
577
|
+
- API keys through Environment Variables
|
484
578
|
- Warm-up / Post-Workflow Agent Interactions
|
485
579
|
- Quick Setup
|
486
580
|
- Interactive Prompt Mode
|
@@ -493,7 +587,12 @@ When `human_input` is set to true for an Agent, it is presented with the option
|
|
493
587
|
- OpenAI o1/o3-mini support with reasoning level
|
494
588
|
- Enhanced Human Input Messaging and Handling
|
495
589
|
- Declarative workflows
|
590
|
+
- Numerous defect fixes
|
496
591
|
|
497
592
|
### Features to add.
|
498
593
|
|
499
594
|
- Chat History Clear.
|
595
|
+
|
596
|
+
```
|
597
|
+
|
598
|
+
```
|
@@ -22,14 +22,17 @@ Prompts and configurations that define your Agent Applications are stored in sim
|
|
22
22
|
|
23
23
|
Chat with individual Agents and Components before, during and after workflow execution to tune and diagnose your application.
|
24
24
|
|
25
|
-
Simple model selection makes testing Model <-> MCP Server interaction painless.
|
25
|
+
Simple model selection makes testing Model <-> MCP Server interaction painless. You can read more about the motivation behind this project [here](https://llmindset.co.uk/resources/fast-agent/)
|
26
|
+
|
27
|
+

|
26
28
|
|
27
29
|
## Get started:
|
28
30
|
|
29
31
|
Start by installing the [uv package manager](https://docs.astral.sh/uv/) for Python. Then:
|
30
32
|
|
31
33
|
```bash
|
32
|
-
uv pip install fast-agent-mcp # install fast-agent
|
34
|
+
uv pip install fast-agent-mcp # install fast-agent!
|
35
|
+
|
33
36
|
fast-agent setup # create an example agent and config files
|
34
37
|
uv run agent.py # run your first agent
|
35
38
|
uv run agent.py --model=o3-mini.low # specify a model
|
@@ -38,6 +41,7 @@ fast-agent bootstrap workflow # create "building effective agents" example
|
|
38
41
|
|
39
42
|
Other bootstrap examples include a Researcher Agent (with Evaluator-Optimizer workflow) and Data Analysis Agent (similar to the ChatGPT experience), demonstrating MCP Roots support.
|
40
43
|
|
44
|
+
> [!TIP]
|
41
45
|
> Windows Users - there are a couple of configuration changes needed for the Filesystem and Docker MCP Servers - necessary changes are detailed within the configuration files.
|
42
46
|
|
43
47
|
### Basic Agents
|
@@ -117,7 +121,7 @@ async def main():
|
|
117
121
|
)
|
118
122
|
```
|
119
123
|
|
120
|
-
All Agents and Workflows respond to `.send("message")`
|
124
|
+
All Agents and Workflows respond to `.send("message")` or `.prompt()` to begin a chat session.
|
121
125
|
|
122
126
|
Saved as `social.py` we can now run this workflow from the command line with:
|
123
127
|
|
@@ -125,7 +129,7 @@ Saved as `social.py` we can now run this workflow from the command line with:
|
|
125
129
|
uv run social.py --agent social_media --message "<url>"
|
126
130
|
```
|
127
131
|
|
128
|
-
Add the `--quiet` switch to only return the final response.
|
132
|
+
Add the `--quiet` switch to only return the final response, which is useful for simple automations.
|
129
133
|
|
130
134
|
## Workflows
|
131
135
|
|
@@ -146,7 +150,7 @@ async with fast.run() as agent:
|
|
146
150
|
|
147
151
|
```
|
148
152
|
|
149
|
-
This starts an interactive session, which produces a short social media post for a given URL. If a _chain_ is prompted
|
153
|
+
This starts an interactive session, which produces a short social media post for a given URL. If a _chain_ is prompted it returns to a chat with last Agent in the chain. You can switch the agent to prompt by typing `@agent-name`.
|
150
154
|
|
151
155
|
Chains can be incorporated in other workflows, or contain other workflow elements (including other Chains). You can set an `instruction` to precisely describe it's capabilities to other workflow steps if needed.
|
152
156
|
|
@@ -170,9 +174,9 @@ The Parallel Workflow sends the same message to multiple Agents simultaneously (
|
|
170
174
|
)
|
171
175
|
```
|
172
176
|
|
173
|
-
Look at the `parallel.py` workflow example for more examples. If you don't specify a `fan-in` agent, the `parallel` returns Agent results verbatim.
|
177
|
+
Look at the `parallel.py` workflow example for more examples. If you don't specify a `fan-in` agent, the `parallel` returns the combined Agent results verbatim.
|
174
178
|
|
175
|
-
|
179
|
+
`parallel` is also useful to ensemble ideas from different LLMs.
|
176
180
|
|
177
181
|
### Evaluator-Optimizer
|
178
182
|
|
@@ -221,20 +225,107 @@ See `orchestrator.py` in the workflow examples.
|
|
221
225
|
|
222
226
|
## Agent Features
|
223
227
|
|
228
|
+
### Calling Agents
|
229
|
+
|
230
|
+
All definitions allow omitting the name and instructions arguments for brevity:
|
231
|
+
|
232
|
+
```python
|
233
|
+
@fast.agent("You are a helpful agent") # Create an agent with a default name.
|
234
|
+
@fast.agent("greeter","Respond cheerfully!") # Create an agent with the name "greeter"
|
235
|
+
|
236
|
+
moon_size = await agent("the moon") # Call the default (first defined agent) with a message
|
237
|
+
|
238
|
+
result = await agent.greeter("Good morning!") # Send a message to an agent by name using dot notation
|
239
|
+
result = await agent.greeter.send("Hello!") # You can call 'send' explicitly
|
240
|
+
|
241
|
+
await agent.greeter() # If no message is specified, a chat session will open
|
242
|
+
await agent.greeter.prompt() # that can be made more explicit
|
243
|
+
await agent.greeter.prompt(default_prompt="OK") # and supports setting a default prompt
|
244
|
+
|
245
|
+
agent["greeter"].send("Good Evening!") # Dictionary access is supported if preferred
|
246
|
+
```
|
247
|
+
|
248
|
+
### Defining Agents
|
249
|
+
|
250
|
+
#### Basic Agent
|
251
|
+
|
224
252
|
```python
|
225
253
|
@fast.agent(
|
226
|
-
name="agent",
|
227
|
-
|
228
|
-
servers=["filesystem"],
|
229
|
-
model="o3-mini.high",
|
230
|
-
use_history=True,
|
231
|
-
|
254
|
+
name="agent", # name of the agent
|
255
|
+
instruction="You are a helpful Agent", # base instruction for the agent
|
256
|
+
servers=["filesystem"], # list of MCP Servers for the agent
|
257
|
+
model="o3-mini.high", # specify a model for the agent
|
258
|
+
use_history=True, # agent maintains chat history
|
259
|
+
request_params={"temperature": 0.7}, # additional parameters for the LLM (or RequestParams())
|
260
|
+
human_input=True, # agent can request human input
|
261
|
+
)
|
262
|
+
```
|
263
|
+
|
264
|
+
#### Chain
|
265
|
+
|
266
|
+
```python
|
267
|
+
@fast.chain(
|
268
|
+
name="chain", # name of the chain
|
269
|
+
sequence=["agent1", "agent2", ...], # list of agents in execution order
|
270
|
+
instruction="instruction", # instruction to describe the chain for other workflows
|
271
|
+
continue_with_final=True, # open chat with agent at end of chain after prompting
|
232
272
|
)
|
233
273
|
```
|
234
274
|
|
235
|
-
|
275
|
+
#### Parallel
|
276
|
+
|
277
|
+
```python
|
278
|
+
@fast.parallel(
|
279
|
+
name="parallel", # name of the parallel workflow
|
280
|
+
fan_out=["agent1", "agent2"], # list of agents to run in parallel
|
281
|
+
fan_in="aggregator", # name of agent that combines results (optional)
|
282
|
+
instruction="instruction", # instruction to describe the parallel for other workflows
|
283
|
+
include_request=True, # include original request in fan-in message
|
284
|
+
)
|
285
|
+
```
|
236
286
|
|
237
|
-
|
287
|
+
#### Evaluator-Optimizer
|
288
|
+
|
289
|
+
```python
|
290
|
+
@fast.evaluator_optimizer(
|
291
|
+
name="researcher", # name of the workflow
|
292
|
+
generator="web_searcher", # name of the content generator agent
|
293
|
+
evaluator="quality_assurance", # name of the evaluator agent
|
294
|
+
min_rating="GOOD", # minimum acceptable quality (EXCELLENT, GOOD, FAIR, POOR)
|
295
|
+
max_refinements=3, # maximum number of refinement iterations
|
296
|
+
)
|
297
|
+
```
|
298
|
+
|
299
|
+
#### Router
|
300
|
+
|
301
|
+
```python
|
302
|
+
@fast.router(
|
303
|
+
name="route", # name of the router
|
304
|
+
agents=["agent1", "agent2", "agent3"], # list of agent names router can delegate to
|
305
|
+
model="o3-mini.high", # specify routing model
|
306
|
+
use_history=True, # router maintains chat history
|
307
|
+
human_input=False, # whether router can request human input
|
308
|
+
)
|
309
|
+
```
|
310
|
+
|
311
|
+
#### Orchestrator
|
312
|
+
|
313
|
+
```python
|
314
|
+
@fast.orchestrator(
|
315
|
+
name="orchestrator", # name of the orchestrator
|
316
|
+
instruction="instruction", # base instruction for the orchestrator
|
317
|
+
agents=["agent1", "agent2"], # list of agent names this orchestrator can use
|
318
|
+
model="o3-mini.high", # specify orchestrator planning model
|
319
|
+
use_history=False, # orchestrator doesn't maintain chat history by default
|
320
|
+
human_input=False, # whether orchestrator can request human input
|
321
|
+
plan_type="full", # planning approach: "full" or "iterative"
|
322
|
+
)
|
323
|
+
```
|
324
|
+
|
325
|
+
### Secrets File
|
326
|
+
|
327
|
+
> [!TIP]
|
328
|
+
> fast-agent will look recursively for a fastagent.secrets.yaml file, so you only need to manage this at the root folder of your agent definitions.
|
238
329
|
|
239
330
|
## Project Notes
|
240
331
|
|
@@ -242,8 +333,11 @@ When `human_input` is set to true for an Agent, it is presented with the option
|
|
242
333
|
|
243
334
|
### llmindset.co.uk fork:
|
244
335
|
|
336
|
+
- Remove instructor use for Orchestrator
|
337
|
+
- Improved handling of Parallel/Fan-In and respose option
|
338
|
+
- XML based generated prompts
|
245
339
|
- "FastAgent" style prototyping, with per-agent models
|
246
|
-
-
|
340
|
+
- API keys through Environment Variables
|
247
341
|
- Warm-up / Post-Workflow Agent Interactions
|
248
342
|
- Quick Setup
|
249
343
|
- Interactive Prompt Mode
|
@@ -256,7 +350,12 @@ When `human_input` is set to true for an Agent, it is presented with the option
|
|
256
350
|
- OpenAI o1/o3-mini support with reasoning level
|
257
351
|
- Enhanced Human Input Messaging and Handling
|
258
352
|
- Declarative workflows
|
353
|
+
- Numerous defect fixes
|
259
354
|
|
260
355
|
### Features to add.
|
261
356
|
|
262
357
|
- Chat History Clear.
|
358
|
+
|
359
|
+
```
|
360
|
+
|
361
|
+
```
|
@@ -313,17 +313,25 @@ def get_settings(config_path: str | None = None) -> Settings:
|
|
313
313
|
with open(config_file, "r", encoding="utf-8") as f:
|
314
314
|
yaml_settings = yaml.safe_load(f) or {}
|
315
315
|
merged_settings = yaml_settings
|
316
|
-
|
317
|
-
#
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
316
|
+
# Look for secrets files recursively up the directory tree
|
317
|
+
# but stop after finding the first one
|
318
|
+
current_dir = config_file.parent
|
319
|
+
found_secrets = False
|
320
|
+
while current_dir != current_dir.parent and not found_secrets:
|
321
|
+
for secrets_filename in [
|
322
|
+
"mcp-agent.secrets.yaml",
|
323
|
+
"mcp_agent.secrets.yaml",
|
324
|
+
"fastagent.secrets.yaml",
|
325
|
+
]:
|
326
|
+
secrets_file = current_dir / secrets_filename
|
327
|
+
if secrets_file.exists():
|
328
|
+
with open(secrets_file, "r", encoding="utf-8") as f:
|
329
|
+
yaml_secrets = yaml.safe_load(f) or {}
|
330
|
+
merged_settings = deep_merge(merged_settings, yaml_secrets)
|
331
|
+
found_secrets = True
|
332
|
+
break
|
333
|
+
if not found_secrets:
|
334
|
+
current_dir = current_dir.parent
|
327
335
|
|
328
336
|
_settings = Settings(**merged_settings)
|
329
337
|
return _settings
|
@@ -3,6 +3,7 @@ Enhanced prompt functionality with advanced prompt_toolkit features.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from typing import List
|
6
|
+
from importlib.metadata import version
|
6
7
|
from prompt_toolkit import PromptSession
|
7
8
|
from prompt_toolkit.formatted_text import HTML
|
8
9
|
from prompt_toolkit.history import InMemoryHistory
|
@@ -15,6 +16,12 @@ from rich import print as rich_print
|
|
15
16
|
|
16
17
|
from mcp_agent.core.exceptions import PromptExitError
|
17
18
|
|
19
|
+
# Get the application version
|
20
|
+
try:
|
21
|
+
app_version = version("fast-agent-mcp")
|
22
|
+
except: # noqa: E722
|
23
|
+
app_version = "unknown"
|
24
|
+
|
18
25
|
# Map of agent names to their history
|
19
26
|
agent_histories = {}
|
20
27
|
|
@@ -204,7 +211,7 @@ async def get_enhanced_input(
|
|
204
211
|
|
205
212
|
shortcut_text = " | ".join(f"{key}:{action}" for key, action in shortcuts)
|
206
213
|
return HTML(
|
207
|
-
f" <{toolbar_color}> {agent_name} </{toolbar_color}> | <b>Mode:</b> <{mode_style}> {mode_text} </{mode_style}> {newline} | {shortcut_text}"
|
214
|
+
f" <{toolbar_color}> {agent_name} </{toolbar_color}> | <b>Mode:</b> <{mode_style}> {mode_text} </{mode_style}> {newline} | {shortcut_text} | <dim>v{app_version}</dim>"
|
208
215
|
)
|
209
216
|
|
210
217
|
# Create session with history and completions
|
@@ -318,7 +325,8 @@ async def handle_special_commands(command, agent_app=None):
|
|
318
325
|
rich_print(
|
319
326
|
" Enter - Submit (normal mode) / New line (multiline mode)"
|
320
327
|
)
|
321
|
-
rich_print("
|
328
|
+
rich_print(" \\ + Enter - Insert new line in normal mode")
|
329
|
+
rich_print(" Ctrl+Enter - Always submit (in any mode)")
|
322
330
|
rich_print(" Ctrl+T - Toggle multiline mode")
|
323
331
|
rich_print(" Ctrl+L - Clear input")
|
324
332
|
rich_print(" Up/Down - Navigate history")
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from mcp_agent.core.fastagent import FastAgent
|
4
|
+
from mcp_agent.workflows.llm.augmented_llm import RequestParams
|
5
|
+
|
6
|
+
# Create the application
|
7
|
+
fast = FastAgent("Data Analysis (Roots)")
|
8
|
+
|
9
|
+
|
10
|
+
@fast.agent(
|
11
|
+
name="data_analysis",
|
12
|
+
instruction="""
|
13
|
+
You have access to a Python 3.12 interpreter and you can use this to analyse and process data.
|
14
|
+
Common analysis packages such as Pandas, Seaborn and Matplotlib are already installed.
|
15
|
+
You can add further packages if needed.
|
16
|
+
Data files are accessible from the /mnt/data/ directory (this is the current working directory).
|
17
|
+
Visualisations should be saved as .png files in the current working directory.
|
18
|
+
""",
|
19
|
+
servers=["interpreter"],
|
20
|
+
request_params=RequestParams(maxTokens=8192),
|
21
|
+
)
|
22
|
+
@fast.agent(
|
23
|
+
"evaluator",
|
24
|
+
"""You are collaborating with a Data Analysis tool that has the capability to analyse data and produce visualisations.
|
25
|
+
You must make sure that the tool has:
|
26
|
+
- Considered the best way for a Human to interpret the data
|
27
|
+
- Produced insightful visualasions.
|
28
|
+
- Provided a high level summary report for the Human.
|
29
|
+
- Has had its findings challenged, and justified
|
30
|
+
""",
|
31
|
+
request_params=RequestParams(maxTokens=8192),
|
32
|
+
)
|
33
|
+
@fast.evaluator_optimizer(
|
34
|
+
"analysis_tool",
|
35
|
+
generator="data_analysis",
|
36
|
+
evaluator="evaluator",
|
37
|
+
max_refinements=3,
|
38
|
+
min_rating="EXCELLENT",
|
39
|
+
)
|
40
|
+
@fast.passthrough(
|
41
|
+
"sample",
|
42
|
+
)
|
43
|
+
async def main():
|
44
|
+
# Use the app's context manager
|
45
|
+
async with fast.run() as agent:
|
46
|
+
# await agent(
|
47
|
+
# "There is a csv file in the current directory. "
|
48
|
+
# "Analyse the file, produce a detailed description of the data, and any patterns it contains.",
|
49
|
+
# )
|
50
|
+
# await agent(
|
51
|
+
# "Consider the data, and how to usefully group it for presentation to a Human. Find insights, using the Python Interpreter as needed.\n"
|
52
|
+
# "Use MatPlotLib to produce insightful visualisations. Save them as '.png' files in the current directory. Be sure to run the code and save the files.\n"
|
53
|
+
# "Produce a summary with major insights to the data",
|
54
|
+
# )
|
55
|
+
await agent.analysis_tool.prompt(
|
56
|
+
"Analyse the CSV File in the working directory"
|
57
|
+
)
|
58
|
+
|
59
|
+
|
60
|
+
if __name__ == "__main__":
|
61
|
+
asyncio.run(main())
|
@@ -38,8 +38,6 @@ fast = FastAgent("Evaluator-Optimizer")
|
|
38
38
|
Summarize your evaluation as a structured response with:
|
39
39
|
- Overall quality rating.
|
40
40
|
- Specific feedback and areas for improvement.""",
|
41
|
-
# instructor doesn't seem to work for sonnet37
|
42
|
-
# model="sonnet35",
|
43
41
|
)
|
44
42
|
# Define the evaluator-optimizer workflow
|
45
43
|
@fast.evaluator_optimizer(
|
@@ -60,10 +60,6 @@ and whispers of a hidden agenda linger among the villagers.
|
|
60
60
|
and give an overall grade based on the feedback.""",
|
61
61
|
model="o3-mini.low",
|
62
62
|
)
|
63
|
-
@fast.agent(
|
64
|
-
name="cats-to-dogs",
|
65
|
-
instruction="you should take any text, and change references about cats to dogs",
|
66
|
-
)
|
67
63
|
@fast.parallel(
|
68
64
|
fan_out=["proofreader", "fact_checker", "style_enforcer"],
|
69
65
|
fan_in="grader",
|