fast-agent-mcp 0.0.16__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fast_agent_mcp-0.0.16.dist-info → fast_agent_mcp-0.1.0.dist-info}/METADATA +11 -10
- {fast_agent_mcp-0.0.16.dist-info → fast_agent_mcp-0.1.0.dist-info}/RECORD +17 -16
- mcp_agent/cli/commands/bootstrap.py +1 -1
- mcp_agent/cli/commands/setup.py +4 -1
- mcp_agent/cli/main.py +13 -3
- mcp_agent/core/agent_app.py +1 -1
- mcp_agent/core/enhanced_prompt.py +3 -3
- mcp_agent/core/fastagent.py +87 -49
- mcp_agent/resources/examples/data-analysis/analysis-campaign.py +188 -0
- mcp_agent/resources/examples/data-analysis/analysis.py +32 -32
- mcp_agent/resources/examples/workflows/evaluator.py +3 -1
- mcp_agent/resources/examples/workflows/orchestrator.py +1 -1
- mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +120 -63
- mcp_agent/workflows/orchestrator/orchestrator.py +114 -66
- {fast_agent_mcp-0.0.16.dist-info → fast_agent_mcp-0.1.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.0.16.dist-info → fast_agent_mcp-0.1.0.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.0.16.dist-info → fast_agent_mcp-0.1.0.dist-info}/licenses/LICENSE +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.1.0
|
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
|
@@ -235,7 +235,7 @@ Provides-Extra: temporal
|
|
235
235
|
Requires-Dist: temporalio>=1.8.0; extra == 'temporal'
|
236
236
|
Description-Content-Type: text/markdown
|
237
237
|
|
238
|
-
##
|
238
|
+
## fast-agent
|
239
239
|
|
240
240
|
<p align="center">
|
241
241
|
<a href="https://pypi.org/project/fast-agent-mcp/"><img src="https://img.shields.io/pypi/v/fast-agent-mcp?color=%2334D058&label=pypi" /></a>
|
@@ -415,9 +415,13 @@ Look at the `parallel.py` workflow example for more examples. If you don't speci
|
|
415
415
|
|
416
416
|
`parallel` is also useful to ensemble ideas from different LLMs.
|
417
417
|
|
418
|
+
When using `parallel` in other workflows, specify an `instruction` to describe its operation.
|
419
|
+
|
418
420
|
### Evaluator-Optimizer
|
419
421
|
|
420
|
-
Evaluator-Optimizers combine 2 agents: one to generate content (the `generator`), and the other to judge that content and provide actionable feedback (the `evaluator`). Messages are sent to the generator first, then the pair run in a loop until either the evaluator is satisfied with the quality, or the maximum number of refinements is reached.
|
422
|
+
Evaluator-Optimizers combine 2 agents: one to generate content (the `generator`), and the other to judge that content and provide actionable feedback (the `evaluator`). Messages are sent to the generator first, then the pair run in a loop until either the evaluator is satisfied with the quality, or the maximum number of refinements is reached. The final result from the Generator is returned.
|
423
|
+
|
424
|
+
If the Generator has `use_history` off, the previous iteration is returned when asking for improvements - otherwise conversational context is used.
|
421
425
|
|
422
426
|
```python
|
423
427
|
@fast.evaluator_optimizer(
|
@@ -432,6 +436,8 @@ async with fast.run() as agent:
|
|
432
436
|
await agent.researcher.send("produce a report on how to make the perfect espresso")
|
433
437
|
```
|
434
438
|
|
439
|
+
When used in a workflow, it returns the last `generator` message as the result.
|
440
|
+
|
435
441
|
See the `evaluator.py` workflow example, or `fast-agent bootstrap researcher` for a more complete example.
|
436
442
|
|
437
443
|
### Router
|
@@ -540,7 +546,7 @@ agent["greeter"].send("Good Evening!") # Dictionary access is supported
|
|
540
546
|
name="route", # name of the router
|
541
547
|
agents=["agent1", "agent2", "agent3"], # list of agent names router can delegate to
|
542
548
|
model="o3-mini.high", # specify routing model
|
543
|
-
use_history=
|
549
|
+
use_history=False, # router maintains conversation history
|
544
550
|
human_input=False, # whether router can request human input
|
545
551
|
)
|
546
552
|
```
|
@@ -570,6 +576,7 @@ agent["greeter"].send("Good Evening!") # Dictionary access is supported
|
|
570
576
|
|
571
577
|
### llmindset.co.uk fork:
|
572
578
|
|
579
|
+
- Overhaul of Eval/Opt for Conversation Management
|
573
580
|
- Remove instructor use for Orchestrator
|
574
581
|
- Improved handling of Parallel/Fan-In and respose option
|
575
582
|
- XML based generated prompts
|
@@ -590,9 +597,3 @@ agent["greeter"].send("Good Evening!") # Dictionary access is supported
|
|
590
597
|
- Numerous defect fixes
|
591
598
|
|
592
599
|
### Features to add.
|
593
|
-
|
594
|
-
- Chat History Clear.
|
595
|
-
|
596
|
-
```
|
597
|
-
|
598
|
-
```
|
@@ -11,19 +11,19 @@ mcp_agent/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
11
11
|
mcp_agent/agents/agent.py,sha256=losanPSdZXZzmeiX-J6ctOinLlkhNZsxwi3Swr8lnxA,11482
|
12
12
|
mcp_agent/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
mcp_agent/cli/__main__.py,sha256=AVZ7tQFhU_sDOGuUGJq8ujgKtcxsYJBJwHbVaaiRDlI,166
|
14
|
-
mcp_agent/cli/main.py,sha256=
|
14
|
+
mcp_agent/cli/main.py,sha256=DE6EZzspfzHwPK59x8vL4AIDHRQkVQ1Ja70XRGU1IQs,2753
|
15
15
|
mcp_agent/cli/terminal.py,sha256=5fqrKlJvIpKEuvpvZ653OueQSYFFktBEbosjr2ucMUc,1026
|
16
|
-
mcp_agent/cli/commands/bootstrap.py,sha256=
|
16
|
+
mcp_agent/cli/commands/bootstrap.py,sha256=Rmwbuwl52eHfnya7fnwKk2J7nCsHpSh6irka4mBDEnU,10779
|
17
17
|
mcp_agent/cli/commands/config.py,sha256=32YTS5jmsYAs9QzAhjkG70_daAHqOemf4XbZBBSMz6g,204
|
18
|
-
mcp_agent/cli/commands/setup.py,sha256=
|
18
|
+
mcp_agent/cli/commands/setup.py,sha256=_SCpd6_PrixqbSaE72JQ7erIRkZnJGmh_3TvvwSzEiE,6392
|
19
19
|
mcp_agent/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
mcp_agent/core/agent_app.py,sha256=
|
20
|
+
mcp_agent/core/agent_app.py,sha256=6U3HLYAJOfyVuUpZVELWT5lOo64-b_sfWp0yn88s7Wo,6085
|
21
21
|
mcp_agent/core/agent_types.py,sha256=yKiMbv9QO2dduq4zXmoMZlOZpXJZhM4oNwIq1-134FE,318
|
22
22
|
mcp_agent/core/agent_utils.py,sha256=yUJ-qvw5TblqqOsB1vj0Qvcz9mass9awPA6UNNvuw0A,1738
|
23
|
-
mcp_agent/core/enhanced_prompt.py,sha256=
|
23
|
+
mcp_agent/core/enhanced_prompt.py,sha256=XraDKdIMW960KXCiMfCEPKDakbf1wHYgvHwD-9CBDi0,13011
|
24
24
|
mcp_agent/core/error_handling.py,sha256=D3HMW5odrbJvaKqcpCGj6eDXrbFcuqYaCZz7fyYiTu4,623
|
25
25
|
mcp_agent/core/exceptions.py,sha256=a2-JGRwFFRoQEPuAq0JC5PhAJ5TO3xVJfdS4-VN29cw,2225
|
26
|
-
mcp_agent/core/fastagent.py,sha256=
|
26
|
+
mcp_agent/core/fastagent.py,sha256=CuT50oaexYq7L5-1xHR5HfS7qYKNToH3wmBAeD8kcBY,58234
|
27
27
|
mcp_agent/core/proxies.py,sha256=hXDUpsgGO4xBTIjdUeXj6vULPb8sf55vAFVQh6Ybn60,4411
|
28
28
|
mcp_agent/core/server_validation.py,sha256=_59cn16nNT4HGPwg19HgxMtHK4MsdWYDUw_CuL-5xek,1696
|
29
29
|
mcp_agent/core/types.py,sha256=Zhi9iW7uiOfdpSt9NC0FCtGRFtJPg4mpZPK2aYi7a7M,817
|
@@ -54,7 +54,8 @@ mcp_agent/mcp/mcp_agent_server.py,sha256=xP09HZTeguJi4Fq0p3fjLBP55uSYe5AdqM90xCg
|
|
54
54
|
mcp_agent/mcp/mcp_aggregator.py,sha256=RVsgNnSJ1IPBkqKgF_Gp-Cpv97FVBIdppPey6FRoHB0,14751
|
55
55
|
mcp_agent/mcp/mcp_connection_manager.py,sha256=WLli0w3TVcsszyD9M7zP7vLKPetnQLTf_0PGhvMm9YM,13145
|
56
56
|
mcp_agent/mcp/stdio.py,sha256=tW075R5rQ-UlflXWFKIFDgCbWbuhKqxhiYolWvyEkFs,3985
|
57
|
-
mcp_agent/resources/examples/data-analysis/analysis.py,sha256=
|
57
|
+
mcp_agent/resources/examples/data-analysis/analysis-campaign.py,sha256=EG-HhaDHltZ4hHAqhgfX_pHM2wem48aYhSIKJxyWHKc,7269
|
58
|
+
mcp_agent/resources/examples/data-analysis/analysis.py,sha256=yRwcYob-jaqwR1vdx_gYXpfqtBN4w7creNeNgimOHa4,2443
|
58
59
|
mcp_agent/resources/examples/data-analysis/fastagent.config.yaml,sha256=eTKGbjnTHhDTeNRPQvG_fr9OQpEZ5Y9v7X2NyCj0V70,530
|
59
60
|
mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv,sha256=pcMeOL1_r8m8MziE6xgbBrQbjl5Ijo98yycZn7O-dlk,227977
|
60
61
|
mcp_agent/resources/examples/internal/agent.py,sha256=f-jTgYabV3nWCQm0ZP9NtSEWjx3nQbRngzArRufcELg,384
|
@@ -66,10 +67,10 @@ mcp_agent/resources/examples/researcher/researcher-eval.py,sha256=kNPjIU-JwE0oIB
|
|
66
67
|
mcp_agent/resources/examples/researcher/researcher.py,sha256=jPRafm7jbpHKkX_dQiYGG3Sw-e1Dm86q-JZT-WZDhM0,1425
|
67
68
|
mcp_agent/resources/examples/workflows/agent_build.py,sha256=vdjS02rZR88RU53WYzXxPscfFNEFFe_niHYE_i49I8Q,2396
|
68
69
|
mcp_agent/resources/examples/workflows/chaining.py,sha256=1G_0XBcFkSJCOXb6N_iXWlSc_oGAlhENR0k_CN1vJKI,1208
|
69
|
-
mcp_agent/resources/examples/workflows/evaluator.py,sha256=
|
70
|
+
mcp_agent/resources/examples/workflows/evaluator.py,sha256=3XmW1mjImlaWb0c5FWHYS9yP8nVGTbEdJySAoWXwrDg,3109
|
70
71
|
mcp_agent/resources/examples/workflows/fastagent.config.yaml,sha256=k2AiapOcK42uqG2nWDVvnSLqN4okQIQZK0FTbZufBpY,809
|
71
72
|
mcp_agent/resources/examples/workflows/human_input.py,sha256=c8cBdLEPbaMXddFwsfN3Z7RFs5PZXsdrjANfvq1VTPM,605
|
72
|
-
mcp_agent/resources/examples/workflows/orchestrator.py,sha256=
|
73
|
+
mcp_agent/resources/examples/workflows/orchestrator.py,sha256=5TGFWrRQiTCdYY738cyd_OzZc7vckYkk1Up9VejFXB0,2574
|
73
74
|
mcp_agent/resources/examples/workflows/parallel.py,sha256=pLbQrtXfbdYqMVddxtg5dZnBnm5Wo2mXlIa1Vf2F1FQ,3096
|
74
75
|
mcp_agent/resources/examples/workflows/router.py,sha256=XT_ewCrxPxdUTMCYQGw34qZQ3GGu8TYY_v5Lige8By4,1707
|
75
76
|
mcp_agent/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -80,7 +81,7 @@ mcp_agent/workflows/embedding/embedding_base.py,sha256=-c20ggQ8s7XhMxRX-WEhOgHE7
|
|
80
81
|
mcp_agent/workflows/embedding/embedding_cohere.py,sha256=OKTJvKD_uEafd4c2uhR5tBjprea1nyvlJOO-3FDqOnk,1540
|
81
82
|
mcp_agent/workflows/embedding/embedding_openai.py,sha256=dntjJ5P-FSMGYuyPZC8MuCU_ehwjXw9wDfzZZuSQN1E,1480
|
82
83
|
mcp_agent/workflows/evaluator_optimizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
83
|
-
mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py,sha256=
|
84
|
+
mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py,sha256=N4HjckQf_boFRxoWJmuvwq1IEnGYW-k8pKtqjpsnLSE,19223
|
84
85
|
mcp_agent/workflows/intent_classifier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
85
86
|
mcp_agent/workflows/intent_classifier/intent_classifier_base.py,sha256=zTbOmq6EY_abOlme4zl28HM4RWNNS6bbHl3tF7SshJ0,4004
|
86
87
|
mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py,sha256=_bWZGukc_q9LdA_Q18UoAMSzhN8tt4K_bRHNUhy7Crw,3997
|
@@ -97,7 +98,7 @@ mcp_agent/workflows/llm/llm_selector.py,sha256=G7pIybuBDwtmyxUDov_QrNYH2FoI0qFRu
|
|
97
98
|
mcp_agent/workflows/llm/model_factory.py,sha256=7zTJrO2ReHa_6dfh_gY6xO8dTySqGFCKlOG9-AMJ-i8,6920
|
98
99
|
mcp_agent/workflows/llm/prompt_utils.py,sha256=EY3eddqnmc_YDUQJFysPnpTH6hr4r2HneeEmX76P8TQ,4948
|
99
100
|
mcp_agent/workflows/orchestrator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
100
|
-
mcp_agent/workflows/orchestrator/orchestrator.py,sha256=
|
101
|
+
mcp_agent/workflows/orchestrator/orchestrator.py,sha256=nyn0vTjUz-lea7nIYY-aoVWOKB2ceNNV4x4z92bP3CI,23638
|
101
102
|
mcp_agent/workflows/orchestrator/orchestrator_models.py,sha256=xTl2vUIqdLPvDAnqA485Hf_A3DD48TWhAbo-jfGrmRE,7182
|
102
103
|
mcp_agent/workflows/orchestrator/orchestrator_prompts.py,sha256=eJSQThfd6Jvr1jTDx104sJI5R684yE55L_edCiWERsQ,6153
|
103
104
|
mcp_agent/workflows/parallel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -114,8 +115,8 @@ mcp_agent/workflows/swarm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
114
115
|
mcp_agent/workflows/swarm/swarm.py,sha256=-lAIeSWDqbGHGRPTvjiP9nIKWvxxy9DAojl9yQzO1Pw,11050
|
115
116
|
mcp_agent/workflows/swarm/swarm_anthropic.py,sha256=pW8zFx5baUWGd5Vw3nIDF2oVOOGNorij4qvGJKdYPcs,1624
|
116
117
|
mcp_agent/workflows/swarm/swarm_openai.py,sha256=wfteywvAGkT5bLmIxX_StHJq8144whYmCRnJASAjOes,1596
|
117
|
-
fast_agent_mcp-0.0.
|
118
|
-
fast_agent_mcp-0.0.
|
119
|
-
fast_agent_mcp-0.0.
|
120
|
-
fast_agent_mcp-0.0.
|
121
|
-
fast_agent_mcp-0.0.
|
118
|
+
fast_agent_mcp-0.1.0.dist-info/METADATA,sha256=hN241Foz895Wj3dxkXWKDVeeTuIWmAT1zh7Jvgpo3Bo,27257
|
119
|
+
fast_agent_mcp-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
120
|
+
fast_agent_mcp-0.1.0.dist-info/entry_points.txt,sha256=2IXtSmDK9XjWN__RWuRIJTgWyW17wJnJ_h-pb0pZAxo,174
|
121
|
+
fast_agent_mcp-0.1.0.dist-info/licenses/LICENSE,sha256=cN3FxDURL9XuzE5mhK9L2paZo82LTfjwCYVT7e3j0e4,10939
|
122
|
+
fast_agent_mcp-0.1.0.dist-info/RECORD,,
|
@@ -135,7 +135,7 @@ def copy_example_files(
|
|
135
135
|
|
136
136
|
def show_overview():
|
137
137
|
"""Display an overview of available examples in a nicely formatted table."""
|
138
|
-
console.print("\n[bold cyan]
|
138
|
+
console.print("\n[bold cyan]fast-agent Example Applications[/bold cyan]")
|
139
139
|
console.print("Build agents and compose workflows through practical examples\n")
|
140
140
|
|
141
141
|
# Create a table for better organization
|
mcp_agent/cli/commands/setup.py
CHANGED
@@ -185,7 +185,7 @@ def init(
|
|
185
185
|
# Check for existing .gitignore
|
186
186
|
needs_gitignore = not find_gitignore(config_path)
|
187
187
|
|
188
|
-
console.print("\n[bold]
|
188
|
+
console.print("\n[bold]fast-agent Setup[/bold]\n")
|
189
189
|
console.print("This will create the following files:")
|
190
190
|
console.print(f" - {config_path}/fastagent.config.yaml")
|
191
191
|
console.print(f" - {config_path}/fastagent.secrets.yaml")
|
@@ -227,6 +227,9 @@ def init(
|
|
227
227
|
console.print(
|
228
228
|
"2. Keep fastagent.secrets.yaml secure and never commit it to version control"
|
229
229
|
)
|
230
|
+
console.print(
|
231
|
+
"3. Update fastagent.config.yaml to set a default model (currently system default is 'haiku')"
|
232
|
+
)
|
230
233
|
console.print("\nTo get started, run:")
|
231
234
|
console.print(" uv run agent.py")
|
232
235
|
else:
|
mcp_agent/cli/main.py
CHANGED
@@ -22,7 +22,14 @@ console = Console()
|
|
22
22
|
|
23
23
|
def show_welcome():
|
24
24
|
"""Show a welcome message with available commands."""
|
25
|
-
|
25
|
+
from importlib.metadata import version
|
26
|
+
|
27
|
+
try:
|
28
|
+
app_version = version("fast-agent-mcp")
|
29
|
+
except: # noqa: E722
|
30
|
+
app_version = "unknown"
|
31
|
+
|
32
|
+
console.print(f"\n[bold]fast-agent (fast-agent-mcp) {app_version}[/bold]")
|
26
33
|
console.print("Build effective agents using Model Context Protocol (MCP)")
|
27
34
|
|
28
35
|
# Create a table for commands
|
@@ -41,8 +48,11 @@ def show_welcome():
|
|
41
48
|
console.print("\n[bold]Getting Started:[/bold]")
|
42
49
|
console.print("1. Set up a new project:")
|
43
50
|
console.print(" fastagent setup")
|
44
|
-
console.print("\n2.
|
45
|
-
console.print(" fastagent bootstrap
|
51
|
+
console.print("\n2. Create Building Effective Agents workflow examples:")
|
52
|
+
console.print(" fastagent bootstrap workflow")
|
53
|
+
console.print("\n3. Explore other examples:")
|
54
|
+
console.print(" fastagent bootstrap")
|
55
|
+
|
46
56
|
console.print("\nUse --help with any command for more information")
|
47
57
|
console.print("Example: fastagent bootstrap --help")
|
48
58
|
|
mcp_agent/core/agent_app.py
CHANGED
@@ -52,7 +52,7 @@ class AgentCompleter(Completer):
|
|
52
52
|
"clear": "Clear the screen",
|
53
53
|
"agents": "List available agents",
|
54
54
|
"STOP": "Stop this prompting session and move to next workflow step",
|
55
|
-
"EXIT": "Exit
|
55
|
+
"EXIT": "Exit fast-agent, terminating any running workflows",
|
56
56
|
**(commands or {}), # Allow custom commands to be passed in
|
57
57
|
}
|
58
58
|
if is_human_input:
|
@@ -319,7 +319,7 @@ async def handle_special_commands(command, agent_app=None):
|
|
319
319
|
rich_print(" @agent_name - Switch to agent")
|
320
320
|
rich_print(" STOP - Return control back to the workflow")
|
321
321
|
rich_print(
|
322
|
-
" EXIT - Exit
|
322
|
+
" EXIT - Exit fast-agent, terminating any running workflows"
|
323
323
|
)
|
324
324
|
rich_print("\n[bold]Keyboard Shortcuts:[/bold]")
|
325
325
|
rich_print(
|
@@ -338,7 +338,7 @@ async def handle_special_commands(command, agent_app=None):
|
|
338
338
|
return True
|
339
339
|
|
340
340
|
elif command == "EXIT":
|
341
|
-
raise PromptExitError("User requested to exit
|
341
|
+
raise PromptExitError("User requested to exit fast-agent session")
|
342
342
|
|
343
343
|
elif command == "LIST_AGENTS":
|
344
344
|
if available_agents:
|
mcp_agent/core/fastagent.py
CHANGED
@@ -89,21 +89,23 @@ class FastAgent(ContextDependent):
|
|
89
89
|
help="Specify the agent to send a message to (used with --message)",
|
90
90
|
)
|
91
91
|
parser.add_argument(
|
92
|
-
"-m",
|
92
|
+
"-m",
|
93
|
+
"--message",
|
93
94
|
help="Message to send to the specified agent (requires --agent)",
|
94
95
|
)
|
95
96
|
parser.add_argument(
|
96
|
-
"--quiet",
|
97
|
+
"--quiet",
|
98
|
+
action="store_true",
|
97
99
|
help="Disable progress display, tool and message logging for cleaner output",
|
98
100
|
)
|
99
101
|
self.args = parser.parse_args()
|
100
|
-
|
102
|
+
|
101
103
|
# Quiet mode will be handled in _load_config()
|
102
104
|
|
103
105
|
self.name = name
|
104
106
|
self.config_path = config_path
|
105
107
|
self._load_config()
|
106
|
-
|
108
|
+
|
107
109
|
# Create the MCPApp with the config
|
108
110
|
self.app = MCPApp(
|
109
111
|
name=name,
|
@@ -244,10 +246,24 @@ class FastAgent(ContextDependent):
|
|
244
246
|
if child_data["type"] == AgentType.BASIC.value:
|
245
247
|
# For basic agents, we'll validate LLM config during creation
|
246
248
|
continue
|
247
|
-
|
249
|
+
# Check if it's a workflow type or has LLM capability
|
250
|
+
# Workflows like EvaluatorOptimizer and Parallel are valid for orchestrator
|
251
|
+
func = child_data["func"]
|
252
|
+
workflow_types = [
|
253
|
+
AgentType.EVALUATOR_OPTIMIZER.value,
|
254
|
+
AgentType.PARALLEL.value,
|
255
|
+
AgentType.ROUTER.value,
|
256
|
+
AgentType.CHAIN.value,
|
257
|
+
]
|
258
|
+
|
259
|
+
if not (
|
260
|
+
isinstance(func, AugmentedLLM)
|
261
|
+
or child_data["type"] in workflow_types
|
262
|
+
or (hasattr(func, "_llm") and func._llm is not None)
|
263
|
+
):
|
248
264
|
raise AgentConfigError(
|
249
265
|
f"Agent '{agent_name}' used by orchestrator '{name}' lacks LLM capability",
|
250
|
-
"All agents used by orchestrators must be LLM-capable",
|
266
|
+
"All agents used by orchestrators must be LLM-capable (either an AugmentedLLM or have an _llm property)",
|
251
267
|
)
|
252
268
|
|
253
269
|
elif agent_type == AgentType.ROUTER.value:
|
@@ -536,7 +552,7 @@ class FastAgent(ContextDependent):
|
|
536
552
|
Args:
|
537
553
|
name: Name of the parallel executing agent
|
538
554
|
fan_out: List of parallel execution agents
|
539
|
-
fan_in: Optional name of collecting agent. If not provided, a passthrough agent
|
555
|
+
fan_in: Optional name of collecting agent. If not provided, a passthrough agent
|
540
556
|
will be created automatically with the name "{name}_fan_in"
|
541
557
|
instruction: Optional instruction for the parallel agent
|
542
558
|
model: Model specification string
|
@@ -547,7 +563,7 @@ class FastAgent(ContextDependent):
|
|
547
563
|
# If fan_in is not provided, create a passthrough agent with a derived name
|
548
564
|
if fan_in is None:
|
549
565
|
passthrough_name = f"{name}_fan_in"
|
550
|
-
|
566
|
+
|
551
567
|
# Register the passthrough agent directly in self.agents
|
552
568
|
self.agents[passthrough_name] = {
|
553
569
|
"config": AgentConfig(
|
@@ -559,10 +575,10 @@ class FastAgent(ContextDependent):
|
|
559
575
|
"type": AgentType.BASIC.value, # Using BASIC type since we're just attaching a PassthroughLLM
|
560
576
|
"func": lambda x: x, # Simple passthrough function (never actually called)
|
561
577
|
}
|
562
|
-
|
578
|
+
|
563
579
|
# Use this passthrough as the fan-in
|
564
580
|
fan_in = passthrough_name
|
565
|
-
|
581
|
+
|
566
582
|
decorator = self._create_decorator(
|
567
583
|
AgentType.PARALLEL,
|
568
584
|
default_instruction="",
|
@@ -589,6 +605,7 @@ class FastAgent(ContextDependent):
|
|
589
605
|
max_refinements: int = 3,
|
590
606
|
use_history: bool = True,
|
591
607
|
request_params: Optional[Dict] = None,
|
608
|
+
instruction: Optional[str] = None,
|
592
609
|
) -> Callable:
|
593
610
|
"""
|
594
611
|
Decorator to create and register an evaluator-optimizer workflow.
|
@@ -601,10 +618,11 @@ class FastAgent(ContextDependent):
|
|
601
618
|
max_refinements: Maximum number of refinement iterations
|
602
619
|
use_history: Whether to maintain conversation history
|
603
620
|
request_params: Additional request parameters for the LLM
|
621
|
+
instruction: Optional instruction for the workflow (if not provided, uses generator's instruction)
|
604
622
|
"""
|
605
623
|
decorator = self._create_decorator(
|
606
624
|
AgentType.EVALUATOR_OPTIMIZER,
|
607
|
-
default_instruction="",
|
625
|
+
default_instruction="", # We'll get instruction from generator or override
|
608
626
|
default_servers=[],
|
609
627
|
default_use_history=True,
|
610
628
|
wrapper_needed=True,
|
@@ -616,6 +634,7 @@ class FastAgent(ContextDependent):
|
|
616
634
|
max_refinements=max_refinements,
|
617
635
|
use_history=use_history,
|
618
636
|
request_params=request_params,
|
637
|
+
instruction=instruction, # Pass through any custom instruction
|
619
638
|
)
|
620
639
|
return decorator
|
621
640
|
|
@@ -645,7 +664,7 @@ class FastAgent(ContextDependent):
|
|
645
664
|
AgentType.ROUTER,
|
646
665
|
default_instruction="",
|
647
666
|
default_servers=[],
|
648
|
-
default_use_history=
|
667
|
+
default_use_history=False,
|
649
668
|
wrapper_needed=True,
|
650
669
|
)(
|
651
670
|
name=name,
|
@@ -708,17 +727,14 @@ class FastAgent(ContextDependent):
|
|
708
727
|
continue_with_final=continue_with_final,
|
709
728
|
)
|
710
729
|
return decorator
|
711
|
-
|
730
|
+
|
712
731
|
def passthrough(
|
713
|
-
self,
|
714
|
-
name: str = "Passthrough",
|
715
|
-
use_history: bool = True,
|
716
|
-
**kwargs
|
732
|
+
self, name: str = "Passthrough", use_history: bool = True, **kwargs
|
717
733
|
) -> Callable:
|
718
734
|
"""
|
719
735
|
Decorator to create and register a passthrough agent.
|
720
736
|
A passthrough agent simply returns any input message without modification.
|
721
|
-
|
737
|
+
|
722
738
|
This is useful for parallel workflows where no fan-in aggregation is needed
|
723
739
|
(the fan-in agent can be a passthrough that simply returns the combined outputs).
|
724
740
|
|
@@ -774,15 +790,17 @@ class FastAgent(ContextDependent):
|
|
774
790
|
if agent_type == AgentType.BASIC:
|
775
791
|
# Get the agent name for special handling
|
776
792
|
agent_name = agent_data["config"].name
|
777
|
-
|
793
|
+
|
778
794
|
# Check if this is an agent that should use the PassthroughLLM
|
779
|
-
if agent_name.endswith("_fan_in") or agent_name.startswith(
|
795
|
+
if agent_name.endswith("_fan_in") or agent_name.startswith(
|
796
|
+
"passthrough"
|
797
|
+
):
|
780
798
|
# Import here to avoid circular imports
|
781
799
|
from mcp_agent.workflows.llm.augmented_llm import PassthroughLLM
|
782
|
-
|
800
|
+
|
783
801
|
# Create basic agent with configuration
|
784
802
|
agent = Agent(config=config, context=agent_app.context)
|
785
|
-
|
803
|
+
|
786
804
|
# Set up a PassthroughLLM directly
|
787
805
|
async with agent:
|
788
806
|
agent._llm = PassthroughLLM(
|
@@ -791,13 +809,13 @@ class FastAgent(ContextDependent):
|
|
791
809
|
agent=agent,
|
792
810
|
default_request_params=config.default_request_params,
|
793
811
|
)
|
794
|
-
|
812
|
+
|
795
813
|
# Store the agent
|
796
814
|
instance = agent
|
797
815
|
else:
|
798
816
|
# Standard basic agent with LLM
|
799
817
|
agent = Agent(config=config, context=agent_app.context)
|
800
|
-
|
818
|
+
|
801
819
|
# Set up LLM with proper configuration
|
802
820
|
async with agent:
|
803
821
|
llm_factory = self._get_model_factory(
|
@@ -805,7 +823,7 @@ class FastAgent(ContextDependent):
|
|
805
823
|
request_params=config.default_request_params,
|
806
824
|
)
|
807
825
|
agent._llm = await agent.attach_llm(llm_factory)
|
808
|
-
|
826
|
+
|
809
827
|
# Store the agent
|
810
828
|
instance = agent
|
811
829
|
|
@@ -885,18 +903,19 @@ class FastAgent(ContextDependent):
|
|
885
903
|
f"evaluator={agent_data['evaluator']}"
|
886
904
|
)
|
887
905
|
|
888
|
-
# TODO: Remove legacy - factory usage is only needed for str evaluators
|
889
|
-
# Later this should only be passed when evaluator is a string
|
890
906
|
optimizer_model = (
|
891
907
|
generator.config.model if isinstance(generator, Agent) else None
|
892
908
|
)
|
909
|
+
|
893
910
|
instance = EvaluatorOptimizerLLM(
|
911
|
+
name=config.name, # Pass name from config
|
894
912
|
generator=generator,
|
895
913
|
evaluator=evaluator,
|
896
914
|
min_rating=QualityRating[agent_data["min_rating"]],
|
897
915
|
max_refinements=agent_data["max_refinements"],
|
898
916
|
llm_factory=self._get_model_factory(model=optimizer_model),
|
899
917
|
context=agent_app.context,
|
918
|
+
instruction=config.instruction, # Pass any custom instruction
|
900
919
|
)
|
901
920
|
|
902
921
|
elif agent_type == AgentType.ROUTER:
|
@@ -1249,77 +1268,96 @@ class FastAgent(ContextDependent):
|
|
1249
1268
|
"""
|
1250
1269
|
active_agents = {}
|
1251
1270
|
had_error = False
|
1252
|
-
|
1271
|
+
|
1253
1272
|
# Handle quiet mode by disabling logger settings after initialization
|
1254
1273
|
quiet_mode = hasattr(self, "args") and self.args.quiet
|
1255
|
-
|
1274
|
+
|
1256
1275
|
try:
|
1257
1276
|
async with self.app.run() as agent_app:
|
1258
1277
|
# Apply quiet mode directly to the context's config if needed
|
1259
|
-
if
|
1278
|
+
if (
|
1279
|
+
quiet_mode
|
1280
|
+
and hasattr(agent_app.context, "config")
|
1281
|
+
and hasattr(agent_app.context.config, "logger")
|
1282
|
+
):
|
1260
1283
|
# Apply after initialization but before agents are created
|
1261
1284
|
agent_app.context.config.logger.progress_display = False
|
1262
1285
|
agent_app.context.config.logger.show_chat = False
|
1263
1286
|
agent_app.context.config.logger.show_tools = False
|
1264
|
-
|
1287
|
+
|
1265
1288
|
# Directly disable the progress display singleton
|
1266
1289
|
from mcp_agent.progress_display import progress_display
|
1290
|
+
|
1267
1291
|
progress_display.stop() # This will stop and hide the display
|
1268
|
-
|
1292
|
+
|
1269
1293
|
# Pre-flight validation
|
1270
1294
|
self._validate_server_references()
|
1271
1295
|
self._validate_workflow_references()
|
1272
1296
|
|
1273
1297
|
# Create all types of agents in dependency order
|
1298
|
+
# First create basic agents
|
1274
1299
|
active_agents = await self._create_basic_agents(agent_app)
|
1275
1300
|
|
1276
|
-
|
1301
|
+
# Create workflow types that don't depend on other workflows first
|
1302
|
+
evaluator_optimizers = await self._create_evaluator_optimizers(
|
1277
1303
|
agent_app, active_agents
|
1278
1304
|
)
|
1305
|
+
active_agents.update(evaluator_optimizers)
|
1306
|
+
|
1307
|
+
# Create parallel agents next as they might be dependencies
|
1279
1308
|
parallel_agents = await self._create_parallel_agents(
|
1280
1309
|
agent_app, active_agents
|
1281
1310
|
)
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1311
|
+
active_agents.update(parallel_agents)
|
1312
|
+
|
1313
|
+
# Create routers next
|
1285
1314
|
routers = await self._create_routers(agent_app, active_agents)
|
1315
|
+
active_agents.update(routers)
|
1316
|
+
|
1317
|
+
# Create chains next
|
1286
1318
|
chains = await self._create_agents_in_dependency_order(
|
1287
1319
|
agent_app, active_agents, AgentType.CHAIN
|
1288
1320
|
)
|
1321
|
+
active_agents.update(chains)
|
1289
1322
|
|
1290
|
-
#
|
1323
|
+
# Create orchestrators last as they might depend on any other agent type
|
1324
|
+
orchestrators = await self._create_orchestrators(
|
1325
|
+
agent_app, active_agents
|
1326
|
+
)
|
1327
|
+
|
1328
|
+
# Add orchestrators to active_agents (other types were already added)
|
1291
1329
|
active_agents.update(orchestrators)
|
1292
|
-
active_agents.update(parallel_agents)
|
1293
|
-
active_agents.update(evaluator_optimizers)
|
1294
|
-
active_agents.update(routers)
|
1295
|
-
active_agents.update(chains)
|
1296
1330
|
|
1297
1331
|
# Create wrapper with all agents
|
1298
1332
|
wrapper = AgentApp(agent_app, active_agents)
|
1299
|
-
|
1333
|
+
|
1300
1334
|
# Handle direct message sending if --agent and --message are provided
|
1301
1335
|
if self.args.agent and self.args.message:
|
1302
1336
|
agent_name = self.args.agent
|
1303
1337
|
message = self.args.message
|
1304
|
-
|
1338
|
+
|
1305
1339
|
if agent_name not in active_agents:
|
1306
1340
|
available_agents = ", ".join(active_agents.keys())
|
1307
|
-
print(
|
1341
|
+
print(
|
1342
|
+
f"\n\nError: Agent '{agent_name}' not found. Available agents: {available_agents}"
|
1343
|
+
)
|
1308
1344
|
raise SystemExit(1)
|
1309
|
-
|
1345
|
+
|
1310
1346
|
try:
|
1311
1347
|
# Get response
|
1312
1348
|
response = await wrapper[agent_name].send(message)
|
1313
|
-
|
1349
|
+
|
1314
1350
|
# Only print the response in quiet mode
|
1315
1351
|
if self.args.quiet:
|
1316
1352
|
print(f"{response}")
|
1317
|
-
|
1353
|
+
|
1318
1354
|
raise SystemExit(0)
|
1319
1355
|
except Exception as e:
|
1320
|
-
print(
|
1356
|
+
print(
|
1357
|
+
f"\n\nError sending message to agent '{agent_name}': {str(e)}"
|
1358
|
+
)
|
1321
1359
|
raise SystemExit(1)
|
1322
|
-
|
1360
|
+
|
1323
1361
|
yield wrapper
|
1324
1362
|
|
1325
1363
|
except ServerConfigError as e:
|