scout-ai 1.2.3 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.vimproject +138 -50
- data/README.md +171 -290
- data/Rakefile +17 -1
- data/VERSION +1 -1
- data/doc/Improvements.md +325 -0
- data/doc/StartHere.md +110 -0
- data/doc/developer/Architecture.md +126 -0
- data/doc/developer/Backends.md +199 -0
- data/doc/developer/ChatLifecycle.md +183 -0
- data/doc/developer/DelegationInternals.md +295 -0
- data/doc/developer/DesignPrinciples.md +245 -0
- data/doc/developer/PromptProcessing.md +292 -0
- data/doc/developer/Provenance.md +317 -0
- data/doc/user/BuildingAgents.md +345 -0
- data/doc/user/Cookbook.md +333 -0
- data/doc/user/CoreConcepts.md +181 -0
- data/doc/user/Delegation.md +191 -0
- data/doc/user/GettingStarted.md +159 -0
- data/doc/user/ManagingContext.md +163 -0
- data/doc/user/MultiAgentWorkflows.md +256 -0
- data/doc/user/Python.md +159 -0
- data/doc/user/RunningInference.md +200 -0
- data/doc/user/ToolCalling.md +193 -0
- data/doc/user/WritingChats.md +197 -0
- data/lib/scout/llm/agent/chat.rb +61 -11
- data/lib/scout/llm/agent/delegate.rb +274 -65
- data/lib/scout/llm/agent/iterate.rb +2 -2
- data/lib/scout/llm/agent/save.rb +273 -0
- data/lib/scout/llm/agent/workflow.rb +164 -0
- data/lib/scout/llm/agent.rb +86 -61
- data/lib/scout/llm/ask.rb +62 -17
- data/lib/scout/llm/backends/anthropic.rb +9 -2
- data/lib/scout/llm/backends/bedrock.rb +15 -3
- data/lib/scout/llm/backends/default.rb +183 -99
- data/lib/scout/llm/backends/glm.rb +58 -0
- data/lib/scout/llm/backends/huggingface.rb +196 -26
- data/lib/scout/llm/backends/ollama.rb +13 -1
- data/lib/scout/llm/backends/openai.rb +0 -2
- data/lib/scout/llm/backends/openwebui.rb +20 -13
- data/lib/scout/llm/backends/relay.rb +22 -22
- data/lib/scout/llm/backends/responses.rb +1 -1
- data/lib/scout/llm/chat/agent_meta.rb +264 -0
- data/lib/scout/llm/chat/annotation.rb +39 -10
- data/lib/scout/llm/chat/parse.rb +28 -6
- data/lib/scout/llm/chat/persist.rb +25 -0
- data/lib/scout/llm/chat/process/clear.rb +41 -6
- data/lib/scout/llm/chat/process/files.rb +21 -6
- data/lib/scout/llm/chat/process/meta.rb +421 -34
- data/lib/scout/llm/chat/process/options.rb +21 -1
- data/lib/scout/llm/chat/process/tools.rb +56 -15
- data/lib/scout/llm/chat/process.rb +4 -0
- data/lib/scout/llm/chat/prompt/shorten_tools.rb +125 -0
- data/lib/scout/llm/chat/prompt/shorten_tools_epoch.rb +365 -0
- data/lib/scout/llm/chat/prompt.rb +48 -0
- data/lib/scout/llm/chat/provenance.rb +775 -0
- data/lib/scout/llm/chat/tool_calls.rb +76 -0
- data/lib/scout/llm/chat.rb +18 -2
- data/lib/scout/llm/embed.rb +11 -3
- data/lib/scout/llm/image.rb +86 -0
- data/lib/scout/llm/mcp.rb +10 -2
- data/lib/scout/llm/rag.rb +3 -3
- data/lib/scout/llm/tools/call.rb +160 -11
- data/lib/scout/llm/tools/knowledge_base.rb +1 -1
- data/lib/scout/llm/tools/workflow.rb +32 -16
- data/lib/scout/model/python/huggingface/causal.rb +23 -5
- data/lib/scout/model/python/huggingface.rb +2 -1
- data/lib/scout-ai.rb +1 -0
- data/python/README.md +197 -14
- data/python/scout_ai/huggingface/eval.py +245 -34
- data/python/tests/test_huggingface_eval.py +58 -0
- data/research/ChatAnalyst-required-changes.md +167 -0
- data/research/agent-delegation-analysis.md +810 -0
- data/research/agent-meta-provenance-integration-plan.md +622 -0
- data/research/agent-workflow-analysis.md +1120 -0
- data/research/backends-analysis.md +836 -0
- data/research/chat-core-analysis.md +946 -0
- data/research/chatanalyst-provenance/00-baseline.md +30 -0
- data/research/chatanalyst-provenance/01-repo-map.md +60 -0
- data/research/chatanalyst-provenance/02-event-reconstruction.md +55 -0
- data/research/chatanalyst-provenance/03-duplication-evidence.md +45 -0
- data/research/chatanalyst-provenance/04-tooling-root-cause.md +57 -0
- data/research/chatanalyst-provenance/05-fix-plan.md +46 -0
- data/research/chatanalyst-provenance/07-critic-review.md +25 -0
- data/research/chatanalyst-provenance/final-report.md +45 -0
- data/research/chatanalyst-provenance/resumption.md +37 -0
- data/research/coding-philosophy-analysis.md +928 -0
- data/research/commands-analysis.md +947 -0
- data/research/multi-agent-patterns-analysis.md +853 -0
- data/research/prompt-strategies-analysis.md +630 -0
- data/research/prov-verbosity-fix-notes.md +77 -0
- data/research/provenance-analysis.md +469 -0
- data/research/provenance-navigation-design.md +640 -0
- data/research/synthesis-report.md +487 -0
- data/research/tools-system-analysis.md +779 -0
- data/scout-ai.gemspec +100 -11
- data/scout_commands/agent/ask +13 -3
- data/scout_commands/agent/kb +2 -0
- data/scout_commands/llm/ask +11 -4
- data/scout_commands/llm/md +76 -0
- data/scout_commands/llm/process_queries +48 -0
- data/scout_commands/llm/prov +602 -0
- data/scout_commands/llm/word +71 -0
- data/scout_commands/workflow/mcp +43 -0
- data/share/word/reference.docx +0 -0
- data/test/etc/AI/mock.yaml +11 -0
- data/test/fixtures/backends/anthropic.json +19 -0
- data/test/fixtures/backends/anthropic_tool_use.json +24 -0
- data/test/fixtures/backends/bedrock.json +8 -0
- data/test/fixtures/backends/bedrock_embedding.json +3 -0
- data/test/fixtures/backends/bedrock_tool_use.json +17 -0
- data/test/fixtures/backends/ollama.json +16 -0
- data/test/fixtures/backends/ollama_tool_call.json +27 -0
- data/test/fixtures/backends/openai_chat.json +21 -0
- data/test/fixtures/backends/openai_chat_tool_call.json +31 -0
- data/test/fixtures/backends/responses.json +33 -0
- data/test/fixtures/backends/responses_tool_call.json +28 -0
- data/test/integration/README.md +32 -0
- data/test/integration/scout/llm/backends/test_endpoints.rb +34 -0
- data/test/integration/scout/llm/backends/test_openwebui.rb +61 -0
- data/test/integration/scout/llm/backends/test_relay.rb +52 -0
- data/test/integration/scout/llm/test_infrastructure.rb +74 -0
- data/test/{scout → integration/scout}/llm/test_mcp.rb +1 -1
- data/test/integration/scout/llm/tools/test_mcp.rb +42 -0
- data/test/integration/scout/model/test_base.rb +91 -0
- data/test/scout/llm/agent/test_chat.rb +8 -2
- data/test/scout/llm/agent/test_save.rb +413 -0
- data/test/scout/llm/agent/test_workflow.rb +110 -0
- data/test/scout/llm/backends/test_anthropic.rb +93 -10
- data/test/scout/llm/backends/test_bedrock.rb +118 -2
- data/test/scout/llm/backends/test_huggingface.rb +137 -42
- data/test/scout/llm/backends/test_ollama.rb +70 -20
- data/test/scout/llm/backends/test_openwebui.rb +42 -40
- data/test/scout/llm/backends/test_relay.rb +4 -2
- data/test/scout/llm/chat/agent_meta_fixtures.rb +131 -0
- data/test/scout/llm/chat/process/test_meta.rb +518 -0
- data/test/scout/llm/chat/process/test_normalize_usage.rb +183 -0
- data/test/scout/llm/chat/test_agent_meta.rb +357 -0
- data/test/scout/llm/chat/test_agent_meta_provenance.rb +467 -0
- data/test/scout/llm/chat/test_agent_meta_tokens.rb +594 -0
- data/test/scout/llm/chat/test_parse.rb +70 -15
- data/test/scout/llm/chat/test_prov_cli.rb +274 -0
- data/test/scout/llm/chat/test_provenance.rb +240 -0
- data/test/scout/llm/chat/test_tool_calls.rb +38 -0
- data/test/scout/llm/test_agent.rb +13 -36
- data/test/scout/llm/test_ask.rb +75 -52
- data/test/scout/llm/test_chat.rb +107 -13
- data/test/scout/llm/test_embed.rb +48 -0
- data/test/scout/llm/test_rag.rb +23 -16
- data/test/scout/llm/test_tools.rb +12 -1
- data/test/scout/llm/tools/test_knowledge_base.rb +0 -1
- data/test/scout/llm/tools/test_mcp.rb +5 -3
- data/test/scout/llm/tools/test_workflow.rb +23 -2
- data/test/scout/model/python/huggingface/causal/test_next_token.rb +11 -5
- data/test/scout/model/python/huggingface/test_causal.rb +9 -3
- data/test/scout/model/python/huggingface/test_classification.rb +11 -2
- data/test/scout/model/python/test_torch.rb +2 -0
- data/test/scout/model/python/torch/test_helpers.rb +4 -0
- data/test/scout/model/test_base.rb +4 -2
- data/test/support/availability.rb +231 -0
- data/test/support/fake_clients.rb +138 -0
- data/test/support/fixtures.rb +21 -0
- data/test/support/infrastructure_probes.rb +136 -0
- data/test/support/mock_backend.rb +215 -0
- data/test/test_helper.rb +32 -2
- metadata +99 -10
- data/doc/Agent.md +0 -327
- data/doc/Chat.md +0 -458
- data/doc/LLM.md +0 -340
- data/doc/RAG.md +0 -129
- data/scout_commands/documenter +0 -148
- data/test/scout/llm/backends/test_openai.rb +0 -192
- data/test/scout/llm/backends/test_responses.rb +0 -238
- data/test/scout/llm/test_parse.rb +0 -98
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Getting Started with Scout-AI
|
|
2
|
+
|
|
3
|
+
This guide helps you install Scout-AI, configure your first inference endpoint,
|
|
4
|
+
and run your first conversation. It is intended for anyone new to the
|
|
5
|
+
framework — both human developers and coding agents.
|
|
6
|
+
|
|
7
|
+
**You should read this if:** you have never used Scout-AI before.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What is Scout-AI?
|
|
12
|
+
|
|
13
|
+
Scout-AI is a framework for building AI applications on top of LLMs. It gives
|
|
14
|
+
you:
|
|
15
|
+
|
|
16
|
+
- **Chats**: plain-text conversation files you can inspect, edit, and version.
|
|
17
|
+
- **Agents**: reusable, stateful assistants with tools and personas.
|
|
18
|
+
- **Tools**: let the model call functions, query databases, or run code.
|
|
19
|
+
- **Multi-agent workflows**: orchestrate specialists to solve complex tasks.
|
|
20
|
+
|
|
21
|
+
Scout-AI is written in Ruby and uses the Scout Workflow engine for
|
|
22
|
+
reproducibility and provenance.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
### Prerequisites
|
|
29
|
+
|
|
30
|
+
- Ruby 3.0+
|
|
31
|
+
- An LLM provider account (OpenAI, Anthropic, etc.) or a local model
|
|
32
|
+
(Ollama, vLLM)
|
|
33
|
+
|
|
34
|
+
### Install Scout-AI
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
gem install scout-ai
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or, if you're working from the source repository:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/mvazque2/scout-ai.git
|
|
44
|
+
cd scout-ai
|
|
45
|
+
bundle install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Set your API key
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# For OpenAI
|
|
52
|
+
export OPENAI_API_KEY="sk-..."
|
|
53
|
+
|
|
54
|
+
# For Anthropic
|
|
55
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Configure your first endpoint
|
|
61
|
+
|
|
62
|
+
An **endpoint** is a named configuration for a provider + model. Configure one
|
|
63
|
+
once and reference it by name.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# OpenAI
|
|
67
|
+
scout-ai config set openai model=gpt-4o
|
|
68
|
+
|
|
69
|
+
# Anthropic
|
|
70
|
+
scout-ai config set anthropic provider=anthropic model=claude-sonnet-4-20250514
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Your first conversation
|
|
76
|
+
|
|
77
|
+
### From the command line
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
scout-ai llm ask "Hello! What can you do?"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
You should see a response from the model.
|
|
84
|
+
|
|
85
|
+
### Using a specific endpoint
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
scout-ai llm ask -e anthropic "Hello!"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Your first chat file
|
|
94
|
+
|
|
95
|
+
Create a file `hello.chat`:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
system:
|
|
99
|
+
|
|
100
|
+
You are a friendly assistant. Keep your answers short.
|
|
101
|
+
|
|
102
|
+
user:
|
|
103
|
+
|
|
104
|
+
What is 2 + 2?
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Run it:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
scout-ai llm ask -c hello.chat
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Your first agent
|
|
116
|
+
|
|
117
|
+
Agents are **named directories**. Create one:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
mkdir -p ~/chats/Agent/Greeter
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Create `~/chats/Agent/Greeter/start_chat`:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
system:
|
|
127
|
+
|
|
128
|
+
You are a friendly greeter. Always greet by name.
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use it from the CLI:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
scout-ai agent ask Greeter "Hi, I'm Alice!"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Or from Ruby:
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
require 'scout-ai'
|
|
141
|
+
|
|
142
|
+
agent = LLM.load_agent('Greeter')
|
|
143
|
+
agent.start
|
|
144
|
+
agent.user "Hi, I'm Alice!"
|
|
145
|
+
puts agent.chat
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Where to go next
|
|
151
|
+
|
|
152
|
+
- **[CoreConcepts.md](CoreConcepts.md)** — understand chats, agents, tools, and
|
|
153
|
+
endpoints.
|
|
154
|
+
- **[WritingChats.md](WritingChats.md)** — master the chat-file format.
|
|
155
|
+
- **[BuildingAgents.md](BuildingAgents.md)** — create agents with tools.
|
|
156
|
+
- **[Cookbook.md](Cookbook.md)** — quick recipes for common tasks.
|
|
157
|
+
|
|
158
|
+
If you want to understand how Scout-AI is implemented internally, see the
|
|
159
|
+
[../developer/](../developer/) documentation.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Managing Context
|
|
2
|
+
|
|
3
|
+
This page explains how Scout-AI handles conversations that grow too long for
|
|
4
|
+
the model's context window, and what you can do to control this behavior. It
|
|
5
|
+
is intended for workflow authors building long-running agents or workflows
|
|
6
|
+
with many tool calls.
|
|
7
|
+
|
|
8
|
+
**You should read this if:** your agents make many tool calls, use large files,
|
|
9
|
+
or run for many turns.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## The problem
|
|
14
|
+
|
|
15
|
+
LLMs have a limited **context window** — the total number of tokens they can
|
|
16
|
+
process in a single inference call. In agent workflows, the context grows as:
|
|
17
|
+
|
|
18
|
+
- The conversation accumulates turns.
|
|
19
|
+
- Tool calls add `function_call` and `function_call_output` messages.
|
|
20
|
+
- File imports add large text blocks.
|
|
21
|
+
|
|
22
|
+
Without management, a long agent session will eventually exceed the context
|
|
23
|
+
window and fail.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## How Scout-AI manages context automatically
|
|
28
|
+
|
|
29
|
+
Scout-AI applies **prompt strategies** — transformations to the conversation
|
|
30
|
+
just before sending it to the model. These are **ephemeral**: they modify only
|
|
31
|
+
what the model sees, never the saved chat file.
|
|
32
|
+
|
|
33
|
+
The main strategy is **tool-call pruning**. When tool calls accumulate, older
|
|
34
|
+
ones are shortened or removed:
|
|
35
|
+
|
|
36
|
+
| Threshold | Default | What happens |
|
|
37
|
+
|-----------|---------|-------------|
|
|
38
|
+
| Max tool calls retained | 40 | Older tool call/result pairs beyond this count are removed |
|
|
39
|
+
| Recent tool outputs at full fidelity | 10 | The 10 most recent tool outputs are kept in full |
|
|
40
|
+
| Character budget for tool outputs | 100,000 | Total characters for all retained tool outputs |
|
|
41
|
+
|
|
42
|
+
This means:
|
|
43
|
+
- The most recent tool calls are always visible in full.
|
|
44
|
+
- Older tool calls are progressively truncated.
|
|
45
|
+
- Very old tool calls are removed entirely.
|
|
46
|
+
|
|
47
|
+
The model never sees a truncated prompt — it simply gets a shorter conversation
|
|
48
|
+
that fits within its context window.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## The `clear` directive
|
|
53
|
+
|
|
54
|
+
You can explicitly clear conversation history using the `clear:` role in chat
|
|
55
|
+
files:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
clear:
|
|
59
|
+
|
|
60
|
+
# Everything before this point is removed from the model's view
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This is useful when:
|
|
64
|
+
- You want to start a new phase of work without prior context cluttering the
|
|
65
|
+
prompt.
|
|
66
|
+
- A large file was imported, used, and is no longer needed.
|
|
67
|
+
- You're chaining agents and want each to start fresh.
|
|
68
|
+
|
|
69
|
+
`clear:` is also ephemeral — it affects what the model sees but does not delete
|
|
70
|
+
the messages from the saved chat file.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Tips for keeping context manageable
|
|
75
|
+
|
|
76
|
+
### Be selective with file imports
|
|
77
|
+
|
|
78
|
+
Instead of importing an entire directory, import only the files you need:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
file: src/main.rb
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Not:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
directory: src/
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Use tools instead of pre-loading data
|
|
91
|
+
|
|
92
|
+
If you're not sure whether data will be needed, declare it as a tool instead of
|
|
93
|
+
importing it. The model will fetch it only if needed:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
introduce: DataLookup
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Rather than:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
file: huge_dataset.json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Break long workflows into steps
|
|
106
|
+
|
|
107
|
+
Instead of one giant conversation, use a Scout workflow to break work into
|
|
108
|
+
steps, each with its own chat:
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
task :analyze => :string do |input|
|
|
112
|
+
# Each step gets its own chat, keeping context focused
|
|
113
|
+
end
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
See [MultiAgentWorkflows.md](MultiAgentWorkflows.md) for patterns.
|
|
117
|
+
|
|
118
|
+
### Delegate to keep conversations focused
|
|
119
|
+
|
|
120
|
+
An orchestrator agent can delegate sub-tasks to specialists. Each specialist
|
|
121
|
+
has its own conversation, keeping the orchestrator's context clean:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
agent.socialize # gives the model an 'ask' tool to delegate
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
See [Delegation.md](Delegation.md) for the delegation API.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## What you see vs. what the model sees
|
|
132
|
+
|
|
133
|
+
It's important to understand that the saved chat file may differ from what the
|
|
134
|
+
model actually saw:
|
|
135
|
+
|
|
136
|
+
| Aspect | Saved chat file | What the model sees |
|
|
137
|
+
|--------|----------------|-------------------|
|
|
138
|
+
| Tool calls | All of them, in full | Possibly truncated/pruned |
|
|
139
|
+
| File contents | Full file text | Same (unless cleared) |
|
|
140
|
+
| `clear:` directives | Present as markers | Everything before is removed |
|
|
141
|
+
| Conversation history | Complete | Recent turns only (after pruning) |
|
|
142
|
+
|
|
143
|
+
This is by design: the saved chat is the **ground truth** of what happened;
|
|
144
|
+
the model's prompt is an **optimized view** for the current inference call.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Common mistakes
|
|
149
|
+
|
|
150
|
+
- **Expecting the saved chat to match the model's input**: They can differ.
|
|
151
|
+
The saved chat is the record; the model's prompt is ephemeral.
|
|
152
|
+
- **Importing too much data**: Large files eat context. Use tools for
|
|
153
|
+
on-demand data access.
|
|
154
|
+
- **Not using `clear:` between phases**: If your workflow has distinct phases,
|
|
155
|
+
clearing between them keeps each phase focused.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Next steps
|
|
160
|
+
|
|
161
|
+
- [WritingChats.md](WritingChats.md) — the `clear:` directive in context.
|
|
162
|
+
- [ToolCalling.md](ToolCalling.md) — tools as an alternative to pre-loading.
|
|
163
|
+
- [Delegation.md](Delegation.md) — splitting work across agents.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Multi-Agent Workflows
|
|
2
|
+
|
|
3
|
+
This page explains how to orchestrate multiple agents inside Scout workflows
|
|
4
|
+
for reproducible, pipeline-style AI applications. It is intended for workflow
|
|
5
|
+
authors building complex, multi-step agent systems.
|
|
6
|
+
|
|
7
|
+
**You should read this if:** you want to build pipelines where agents
|
|
8
|
+
collaborate, pass artifacts, and produce tracked, reproducible results.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The idea
|
|
13
|
+
|
|
14
|
+
Scout-AI agents are powerful on their own, but for complex applications you
|
|
15
|
+
often need:
|
|
16
|
+
|
|
17
|
+
- **Multiple steps** — plan, search, execute, review.
|
|
18
|
+
- **Specialized agents** — each with different tools and personas.
|
|
19
|
+
- **Reproducibility** — the same inputs should produce the same results.
|
|
20
|
+
- **Provenance** — you should be able to trace what each agent did.
|
|
21
|
+
|
|
22
|
+
Scout workflows provide all of this. You define tasks that load and run agents,
|
|
23
|
+
and the workflow engine handles caching, dependencies, and provenance.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## The chat_task helper
|
|
28
|
+
|
|
29
|
+
The core building block is `chat_task` — a Scout workflow task that runs an
|
|
30
|
+
agent:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
module MyWorkflow
|
|
34
|
+
extend Workflow
|
|
35
|
+
chat_task :analyze do
|
|
36
|
+
agent = self.agent('Analyst', chat: chat)
|
|
37
|
+
agent.start
|
|
38
|
+
agent.user "Analyze this data."
|
|
39
|
+
result = agent.chat
|
|
40
|
+
agent.answer
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The `chat_task` helper and the `agent` method are available in any workflow
|
|
46
|
+
that includes the `AgentWorkflow` mixin.
|
|
47
|
+
|
|
48
|
+
### What `chat_task` gives you
|
|
49
|
+
|
|
50
|
+
- **Caching**: The same chat input produces the same output, cached on disk.
|
|
51
|
+
- **Provenance**: Every agent run is recorded with full chat history.
|
|
52
|
+
- **Agent chat sidecar**: the agent's own conversation is always written to
|
|
53
|
+
`<job>.files/<name>.chat` next to the job (`agent.chat` by default,
|
|
54
|
+
`worker.chat`/`critic.chat` for named agents), holding the **full** chat
|
|
55
|
+
(system prompt, tools, every turn), while the job **result** keeps delta
|
|
56
|
+
semantics — only the messages produced by this run.
|
|
57
|
+
- **Provenance includes the society tree**: `scout-ai llm prov` treats a job
|
|
58
|
+
and a saved chat the same way here — both are scanned for conversations
|
|
59
|
+
under `<path>.files/`, namely `<path>.files/*.chat`,
|
|
60
|
+
`<path>.files/*.society/<agent>/<conversation>/` and the legacy
|
|
61
|
+
`<path>.files/log/**` (older scouts, still readable). A saved chat skips
|
|
62
|
+
only its own top-level copy at `<chat>.files/<name>.chat` (and the legacy
|
|
63
|
+
`<chat>.files/log/agent.chat`); society conversations keep the same
|
|
64
|
+
`agent.chat` name and are included.
|
|
65
|
+
- **Lazy society tree**: delegated specialist conversations, if any, are
|
|
66
|
+
saved under `<job>.files/<name>.society/<agent_name>/<conversation>/…`, but
|
|
67
|
+
only when they exist. Nothing is created eagerly — no job starts with an
|
|
68
|
+
empty `.files` directory — and parent directories appear on demand.
|
|
69
|
+
- **Dependency tracking**: Tasks can depend on each other.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## A simple pipeline
|
|
74
|
+
|
|
75
|
+
Here's a three-step pipeline: Plan → Execute → Review.
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
module Pipeline
|
|
79
|
+
extend Workflow
|
|
80
|
+
include AgentWorkflow
|
|
81
|
+
|
|
82
|
+
chat_task :plan do |objective|
|
|
83
|
+
agent = self.agent('Planner', chat: chat)
|
|
84
|
+
agent.start
|
|
85
|
+
agent.user objective
|
|
86
|
+
agent.chat
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
chat_task :execute do |plan|
|
|
90
|
+
agent = self.agent('Executor', chat: chat)
|
|
91
|
+
agent.socialize # executor can delegate to specialists
|
|
92
|
+
agent.start
|
|
93
|
+
agent.user "Execute this plan:\n#{plan}"
|
|
94
|
+
agent.chat
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
chat_task :review do |result|
|
|
98
|
+
agent = self.agent('Critic', chat: chat)
|
|
99
|
+
agent.start
|
|
100
|
+
agent.user "Review this result:\n#{result}"
|
|
101
|
+
agent.chat
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Each task gets its own agent, its own chat, and its own provenance trail.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Artifact-first collaboration
|
|
111
|
+
|
|
112
|
+
When agents need to share information, prefer **artifacts** (files on disk)
|
|
113
|
+
over passing everything through the conversation:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
chat_task :search do |query|
|
|
117
|
+
agent = self.agent('Searcher', chat: chat)
|
|
118
|
+
agent.start
|
|
119
|
+
agent.user "Research: #{query}"
|
|
120
|
+
report = agent.chat
|
|
121
|
+
# Save the report as an artifact
|
|
122
|
+
Step.write_file('research_report.md', report)
|
|
123
|
+
report
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
chat_task :synthesize do |report|
|
|
127
|
+
# Read the artifact rather than relying on conversation memory
|
|
128
|
+
full_report = Step.read_file('research_report.md')
|
|
129
|
+
agent = self.agent('Writer', chat: chat)
|
|
130
|
+
agent.start
|
|
131
|
+
agent.user "Write a summary based on this report:\n#{full_report}"
|
|
132
|
+
agent.chat
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Benefits:
|
|
137
|
+
- Each agent's context stays focused on its own task.
|
|
138
|
+
- Artifacts are inspectable and debuggable.
|
|
139
|
+
- Large outputs don't bloat the orchestrator's conversation.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Delegation within workflows
|
|
144
|
+
|
|
145
|
+
Agents in workflows can also delegate to each other:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
chat_task :run do
|
|
149
|
+
agent = self.agent('Manager', chat: chat)
|
|
150
|
+
agent.socialize # model can call ask(agent: 'Worker', prompt: ...)
|
|
151
|
+
agent.start
|
|
152
|
+
agent.user "Complete this project."
|
|
153
|
+
agent.chat
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The model decides when to delegate and to whom. Each delegation creates its
|
|
158
|
+
own provenance entry.
|
|
159
|
+
|
|
160
|
+
See [Delegation.md](Delegation.md) for the full delegation API.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Common patterns
|
|
165
|
+
|
|
166
|
+
### Linear pipeline
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
Plan → Execute → Review → Report
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Each step depends on the previous one. Simple and predictable.
|
|
173
|
+
|
|
174
|
+
### Manager-worker
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Manager → delegates to → Worker(s)
|
|
178
|
+
← returns to ←
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The manager agent has `socialize` enabled and dynamically delegates to
|
|
182
|
+
specialists.
|
|
183
|
+
|
|
184
|
+
### Critic loop
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
Executor → produces → Critic → reviews → Executor → refines → Critic → ...
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Repeat until the critic approves or a max iteration count is reached.
|
|
191
|
+
|
|
192
|
+
### Branched exploration
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
→ Agent A →
|
|
196
|
+
Orchestrator → Agent B → Synthesizer
|
|
197
|
+
→ Agent C →
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Multiple agents work in parallel on different aspects, then a synthesizer
|
|
201
|
+
combines results.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Logging agent activity
|
|
206
|
+
|
|
207
|
+
When agents run inside workflow tasks, the agent's own conversation is saved
|
|
208
|
+
to `<job>.files/<name>.chat` (the full chat; `agent.chat` by default,
|
|
209
|
+
`worker.chat` for a `worker` agent), the job result keeps only
|
|
210
|
+
this run's delta, and delegated specialist conversations — when they exist —
|
|
211
|
+
are saved under `<job>.files/<name>.society/<agent_name>/<conversation>/…`.
|
|
212
|
+
Nothing is created up front; directories and files appear only when there is
|
|
213
|
+
something to save.
|
|
214
|
+
|
|
215
|
+
Chats saved by the CLI get the same sidecar layout: the root conversation is
|
|
216
|
+
copied to `<chat>.files/<name>.chat` and any socialized agents land under
|
|
217
|
+
`<chat>.files/<name>.society/…`. Both jobs and saved chats are examined for
|
|
218
|
+
those conversations, so you can inspect either as provenance:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
scout-ai llm prov /path/to/job
|
|
222
|
+
scout-ai llm prov /path/to/saved.chat
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
This shows the full chat history, including any delegations and tool calls.
|
|
226
|
+
Jobs are recognized by their `.info` sidecar; a `.files` directory alone does
|
|
227
|
+
not make a path a job, because saved chats have one too.
|
|
228
|
+
|
|
229
|
+
Restart snapshots (`.files/resets/<timestamp>.chat`, taken by `agent.start`
|
|
230
|
+
when a prior non-empty chat existed) sit outside `log/` and are recovery
|
|
231
|
+
artifacts, not provenance logs.
|
|
232
|
+
|
|
233
|
+
See [../developer/Provenance.md](../developer/Provenance.md) for provenance
|
|
234
|
+
internals and [BuildingAgents.md](BuildingAgents.md) for save semantics.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Common mistakes
|
|
239
|
+
|
|
240
|
+
- **Trying to do everything in one giant chat**: Break work into tasks. Each
|
|
241
|
+
task gets a fresh context.
|
|
242
|
+
- **Passing everything through conversation**: Use artifacts (files) for large
|
|
243
|
+
outputs between agents.
|
|
244
|
+
- **Not using `socialize` when the model should decide**: If you want dynamic
|
|
245
|
+
delegation, enable `socialize` and let the model choose.
|
|
246
|
+
- **Forgetting that tasks are cached**: If you change an agent's `start_chat`
|
|
247
|
+
but not the task input, you may get a cached result. Clear the cache or
|
|
248
|
+
change the input.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Next steps
|
|
253
|
+
|
|
254
|
+
- [Delegation.md](Delegation.md) — the delegation API.
|
|
255
|
+
- [BuildingAgents.md](BuildingAgents.md) — creating agents.
|
|
256
|
+
- [ManagingContext.md](ManagingContext.md) — keeping contexts focused.
|