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.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +138 -50
  3. data/README.md +171 -290
  4. data/Rakefile +17 -1
  5. data/VERSION +1 -1
  6. data/doc/Improvements.md +325 -0
  7. data/doc/StartHere.md +110 -0
  8. data/doc/developer/Architecture.md +126 -0
  9. data/doc/developer/Backends.md +199 -0
  10. data/doc/developer/ChatLifecycle.md +183 -0
  11. data/doc/developer/DelegationInternals.md +295 -0
  12. data/doc/developer/DesignPrinciples.md +245 -0
  13. data/doc/developer/PromptProcessing.md +292 -0
  14. data/doc/developer/Provenance.md +317 -0
  15. data/doc/user/BuildingAgents.md +345 -0
  16. data/doc/user/Cookbook.md +333 -0
  17. data/doc/user/CoreConcepts.md +181 -0
  18. data/doc/user/Delegation.md +191 -0
  19. data/doc/user/GettingStarted.md +159 -0
  20. data/doc/user/ManagingContext.md +163 -0
  21. data/doc/user/MultiAgentWorkflows.md +256 -0
  22. data/doc/user/Python.md +159 -0
  23. data/doc/user/RunningInference.md +200 -0
  24. data/doc/user/ToolCalling.md +193 -0
  25. data/doc/user/WritingChats.md +197 -0
  26. data/lib/scout/llm/agent/chat.rb +61 -11
  27. data/lib/scout/llm/agent/delegate.rb +274 -65
  28. data/lib/scout/llm/agent/iterate.rb +2 -2
  29. data/lib/scout/llm/agent/save.rb +273 -0
  30. data/lib/scout/llm/agent/workflow.rb +164 -0
  31. data/lib/scout/llm/agent.rb +86 -61
  32. data/lib/scout/llm/ask.rb +62 -17
  33. data/lib/scout/llm/backends/anthropic.rb +9 -2
  34. data/lib/scout/llm/backends/bedrock.rb +15 -3
  35. data/lib/scout/llm/backends/default.rb +183 -99
  36. data/lib/scout/llm/backends/glm.rb +58 -0
  37. data/lib/scout/llm/backends/huggingface.rb +196 -26
  38. data/lib/scout/llm/backends/ollama.rb +13 -1
  39. data/lib/scout/llm/backends/openai.rb +0 -2
  40. data/lib/scout/llm/backends/openwebui.rb +20 -13
  41. data/lib/scout/llm/backends/relay.rb +22 -22
  42. data/lib/scout/llm/backends/responses.rb +1 -1
  43. data/lib/scout/llm/chat/agent_meta.rb +264 -0
  44. data/lib/scout/llm/chat/annotation.rb +39 -10
  45. data/lib/scout/llm/chat/parse.rb +28 -6
  46. data/lib/scout/llm/chat/persist.rb +25 -0
  47. data/lib/scout/llm/chat/process/clear.rb +41 -6
  48. data/lib/scout/llm/chat/process/files.rb +21 -6
  49. data/lib/scout/llm/chat/process/meta.rb +421 -34
  50. data/lib/scout/llm/chat/process/options.rb +21 -1
  51. data/lib/scout/llm/chat/process/tools.rb +56 -15
  52. data/lib/scout/llm/chat/process.rb +4 -0
  53. data/lib/scout/llm/chat/prompt/shorten_tools.rb +125 -0
  54. data/lib/scout/llm/chat/prompt/shorten_tools_epoch.rb +365 -0
  55. data/lib/scout/llm/chat/prompt.rb +48 -0
  56. data/lib/scout/llm/chat/provenance.rb +775 -0
  57. data/lib/scout/llm/chat/tool_calls.rb +76 -0
  58. data/lib/scout/llm/chat.rb +18 -2
  59. data/lib/scout/llm/embed.rb +11 -3
  60. data/lib/scout/llm/image.rb +86 -0
  61. data/lib/scout/llm/mcp.rb +10 -2
  62. data/lib/scout/llm/rag.rb +3 -3
  63. data/lib/scout/llm/tools/call.rb +160 -11
  64. data/lib/scout/llm/tools/knowledge_base.rb +1 -1
  65. data/lib/scout/llm/tools/workflow.rb +32 -16
  66. data/lib/scout/model/python/huggingface/causal.rb +23 -5
  67. data/lib/scout/model/python/huggingface.rb +2 -1
  68. data/lib/scout-ai.rb +1 -0
  69. data/python/README.md +197 -14
  70. data/python/scout_ai/huggingface/eval.py +245 -34
  71. data/python/tests/test_huggingface_eval.py +58 -0
  72. data/research/ChatAnalyst-required-changes.md +167 -0
  73. data/research/agent-delegation-analysis.md +810 -0
  74. data/research/agent-meta-provenance-integration-plan.md +622 -0
  75. data/research/agent-workflow-analysis.md +1120 -0
  76. data/research/backends-analysis.md +836 -0
  77. data/research/chat-core-analysis.md +946 -0
  78. data/research/chatanalyst-provenance/00-baseline.md +30 -0
  79. data/research/chatanalyst-provenance/01-repo-map.md +60 -0
  80. data/research/chatanalyst-provenance/02-event-reconstruction.md +55 -0
  81. data/research/chatanalyst-provenance/03-duplication-evidence.md +45 -0
  82. data/research/chatanalyst-provenance/04-tooling-root-cause.md +57 -0
  83. data/research/chatanalyst-provenance/05-fix-plan.md +46 -0
  84. data/research/chatanalyst-provenance/07-critic-review.md +25 -0
  85. data/research/chatanalyst-provenance/final-report.md +45 -0
  86. data/research/chatanalyst-provenance/resumption.md +37 -0
  87. data/research/coding-philosophy-analysis.md +928 -0
  88. data/research/commands-analysis.md +947 -0
  89. data/research/multi-agent-patterns-analysis.md +853 -0
  90. data/research/prompt-strategies-analysis.md +630 -0
  91. data/research/prov-verbosity-fix-notes.md +77 -0
  92. data/research/provenance-analysis.md +469 -0
  93. data/research/provenance-navigation-design.md +640 -0
  94. data/research/synthesis-report.md +487 -0
  95. data/research/tools-system-analysis.md +779 -0
  96. data/scout-ai.gemspec +100 -11
  97. data/scout_commands/agent/ask +13 -3
  98. data/scout_commands/agent/kb +2 -0
  99. data/scout_commands/llm/ask +11 -4
  100. data/scout_commands/llm/md +76 -0
  101. data/scout_commands/llm/process_queries +48 -0
  102. data/scout_commands/llm/prov +602 -0
  103. data/scout_commands/llm/word +71 -0
  104. data/scout_commands/workflow/mcp +43 -0
  105. data/share/word/reference.docx +0 -0
  106. data/test/etc/AI/mock.yaml +11 -0
  107. data/test/fixtures/backends/anthropic.json +19 -0
  108. data/test/fixtures/backends/anthropic_tool_use.json +24 -0
  109. data/test/fixtures/backends/bedrock.json +8 -0
  110. data/test/fixtures/backends/bedrock_embedding.json +3 -0
  111. data/test/fixtures/backends/bedrock_tool_use.json +17 -0
  112. data/test/fixtures/backends/ollama.json +16 -0
  113. data/test/fixtures/backends/ollama_tool_call.json +27 -0
  114. data/test/fixtures/backends/openai_chat.json +21 -0
  115. data/test/fixtures/backends/openai_chat_tool_call.json +31 -0
  116. data/test/fixtures/backends/responses.json +33 -0
  117. data/test/fixtures/backends/responses_tool_call.json +28 -0
  118. data/test/integration/README.md +32 -0
  119. data/test/integration/scout/llm/backends/test_endpoints.rb +34 -0
  120. data/test/integration/scout/llm/backends/test_openwebui.rb +61 -0
  121. data/test/integration/scout/llm/backends/test_relay.rb +52 -0
  122. data/test/integration/scout/llm/test_infrastructure.rb +74 -0
  123. data/test/{scout → integration/scout}/llm/test_mcp.rb +1 -1
  124. data/test/integration/scout/llm/tools/test_mcp.rb +42 -0
  125. data/test/integration/scout/model/test_base.rb +91 -0
  126. data/test/scout/llm/agent/test_chat.rb +8 -2
  127. data/test/scout/llm/agent/test_save.rb +413 -0
  128. data/test/scout/llm/agent/test_workflow.rb +110 -0
  129. data/test/scout/llm/backends/test_anthropic.rb +93 -10
  130. data/test/scout/llm/backends/test_bedrock.rb +118 -2
  131. data/test/scout/llm/backends/test_huggingface.rb +137 -42
  132. data/test/scout/llm/backends/test_ollama.rb +70 -20
  133. data/test/scout/llm/backends/test_openwebui.rb +42 -40
  134. data/test/scout/llm/backends/test_relay.rb +4 -2
  135. data/test/scout/llm/chat/agent_meta_fixtures.rb +131 -0
  136. data/test/scout/llm/chat/process/test_meta.rb +518 -0
  137. data/test/scout/llm/chat/process/test_normalize_usage.rb +183 -0
  138. data/test/scout/llm/chat/test_agent_meta.rb +357 -0
  139. data/test/scout/llm/chat/test_agent_meta_provenance.rb +467 -0
  140. data/test/scout/llm/chat/test_agent_meta_tokens.rb +594 -0
  141. data/test/scout/llm/chat/test_parse.rb +70 -15
  142. data/test/scout/llm/chat/test_prov_cli.rb +274 -0
  143. data/test/scout/llm/chat/test_provenance.rb +240 -0
  144. data/test/scout/llm/chat/test_tool_calls.rb +38 -0
  145. data/test/scout/llm/test_agent.rb +13 -36
  146. data/test/scout/llm/test_ask.rb +75 -52
  147. data/test/scout/llm/test_chat.rb +107 -13
  148. data/test/scout/llm/test_embed.rb +48 -0
  149. data/test/scout/llm/test_rag.rb +23 -16
  150. data/test/scout/llm/test_tools.rb +12 -1
  151. data/test/scout/llm/tools/test_knowledge_base.rb +0 -1
  152. data/test/scout/llm/tools/test_mcp.rb +5 -3
  153. data/test/scout/llm/tools/test_workflow.rb +23 -2
  154. data/test/scout/model/python/huggingface/causal/test_next_token.rb +11 -5
  155. data/test/scout/model/python/huggingface/test_causal.rb +9 -3
  156. data/test/scout/model/python/huggingface/test_classification.rb +11 -2
  157. data/test/scout/model/python/test_torch.rb +2 -0
  158. data/test/scout/model/python/torch/test_helpers.rb +4 -0
  159. data/test/scout/model/test_base.rb +4 -2
  160. data/test/support/availability.rb +231 -0
  161. data/test/support/fake_clients.rb +138 -0
  162. data/test/support/fixtures.rb +21 -0
  163. data/test/support/infrastructure_probes.rb +136 -0
  164. data/test/support/mock_backend.rb +215 -0
  165. data/test/test_helper.rb +32 -2
  166. metadata +99 -10
  167. data/doc/Agent.md +0 -327
  168. data/doc/Chat.md +0 -458
  169. data/doc/LLM.md +0 -340
  170. data/doc/RAG.md +0 -129
  171. data/scout_commands/documenter +0 -148
  172. data/test/scout/llm/backends/test_openai.rb +0 -192
  173. data/test/scout/llm/backends/test_responses.rb +0 -238
  174. 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.