scout-ai 1.2.5 → 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 +111 -31
- data/README.md +171 -320
- 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 +62 -12
- 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 +36 -6
- data/lib/scout/llm/backends/anthropic.rb +9 -1
- data/lib/scout/llm/backends/bedrock.rb +15 -3
- data/lib/scout/llm/backends/default.rb +129 -89
- data/lib/scout/llm/backends/glm.rb +58 -0
- data/lib/scout/llm/backends/huggingface.rb +13 -1
- data/lib/scout/llm/backends/ollama.rb +13 -0
- data/lib/scout/llm/backends/openwebui.rb +8 -3
- data/lib/scout/llm/chat/agent_meta.rb +264 -0
- data/lib/scout/llm/chat/annotation.rb +37 -14
- 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 +19 -1
- data/lib/scout/llm/chat/process/files.rb +16 -1
- data/lib/scout/llm/chat/process/meta.rb +422 -32
- data/lib/scout/llm/chat/process/options.rb +21 -1
- data/lib/scout/llm/chat/process/tools.rb +49 -12
- 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 +8 -3
- data/lib/scout/llm/image.rb +86 -0
- data/lib/scout/llm/rag.rb +3 -3
- data/lib/scout/llm/tools/call.rb +159 -10
- data/lib/scout/llm/tools/knowledge_base.rb +1 -1
- data/lib/scout/llm/tools/workflow.rb +13 -5
- data/lib/scout-ai.rb +1 -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 +97 -13
- 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/prov +602 -0
- data/scout_commands/llm/word +71 -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_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 +96 -12
- data/doc/Agent.md +0 -354
- data/doc/Chat.md +0 -481
- data/doc/LLM.md +0 -356
- data/doc/PythonAgentTasks.md +0 -333
- data/doc/RAG.md +0 -129
- data/doc/USER_GUIDE.md +0 -572
- 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
data/doc/Chat.md
DELETED
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
# Chat
|
|
2
|
-
|
|
3
|
-
`Chat` is Scout-AI’s conversation format.
|
|
4
|
-
|
|
5
|
-
It serves two related purposes:
|
|
6
|
-
|
|
7
|
-
1) **An on-disk “chat file” format** (human editable) where each message is written as:
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
role:
|
|
11
|
-
|
|
12
|
-
...content...
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
2) **A Ruby builder** over an `Array` of `{role:, content:}` hashes.
|
|
16
|
-
|
|
17
|
-
The important nuance: a chat is not just prompts. In addition to `user/system/assistant`, Scout-AI supports “control” roles that are interpreted by `LLM.chat` **before** the model is queried:
|
|
18
|
-
|
|
19
|
-
- imports (`import`, `continue`, `last`)
|
|
20
|
-
- files (`file`, `directory`, `image`, `pdf`)
|
|
21
|
-
- workflow integration (`tool`, `task`, `inline_task`, `job`, `inline_job`)
|
|
22
|
-
- knowledge base integration (`association`, `kb`)
|
|
23
|
-
- MCP tool integration (`mcp`)
|
|
24
|
-
- options (`endpoint`, `backend`, `model`, `format`, `persist`, `previous_response_id`, `option`, `sticky_option`)
|
|
25
|
-
- conversation maintenance (`clear`, `skip`, `clear_tools`, `clear_associations`)
|
|
26
|
-
|
|
27
|
-
This document is the reference for **all chat roles and options**, and how they behave.
|
|
28
|
-
|
|
29
|
-
Related docs:
|
|
30
|
-
|
|
31
|
-
- `USER_GUIDE.md` — first practical guide to chats, agents, workflows, and multi-agent patterns
|
|
32
|
-
- `../python/README.md` — Python SDK for `Chat` and `Agent` wrappers
|
|
33
|
-
- `doc/LLM.md` — how `LLM.ask` expands/executes chats and calls backends
|
|
34
|
-
- `doc/Agent.md` — stateful agents and programmatic control loops
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## 0. Mental model
|
|
39
|
-
|
|
40
|
-
A chat file is best understood as two things at once:
|
|
41
|
-
|
|
42
|
-
- a persistent conversation record
|
|
43
|
-
- a declarative control surface for tools, files, jobs, and options
|
|
44
|
-
|
|
45
|
-
The roles fall into a few families:
|
|
46
|
-
|
|
47
|
-
- conversation: `system`, `user`, `assistant`
|
|
48
|
-
- composition: `import`, `continue`, `last`
|
|
49
|
-
- attached context: `file`, `directory`, `image`, `pdf`
|
|
50
|
-
- executable toolkits: `introduce`, `tool`, `task`, `exec_task`, `job`, `inline_job`
|
|
51
|
-
- retrieval and external tool providers: `association`, `kb`, `mcp`
|
|
52
|
-
- runtime options: `endpoint`, `backend`, `model`, `format`, `persist`, `previous_response_id`, `option`, `sticky_option`
|
|
53
|
-
- maintenance: `clear`, `skip`, `clear_tools`, `clear_associations`
|
|
54
|
-
|
|
55
|
-
For a tutorial-style walkthrough, start with `USER_GUIDE.md` and come back here as a reference.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 1. Data model
|
|
60
|
-
|
|
61
|
-
A chat is an array of messages.
|
|
62
|
-
|
|
63
|
-
Each message is a Hash:
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
{ role: "user", content: "Hello" }
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Roles are strings (symbols are accepted but are stringified).
|
|
70
|
-
|
|
71
|
-
In Ruby, `Chat.setup(array)` annotates an array so it gains the builder methods (`user`, `system`, `file`, …).
|
|
72
|
-
|
|
73
|
-
```ruby
|
|
74
|
-
chat = Chat.setup([])
|
|
75
|
-
chat.system "You are a helpful assistant"
|
|
76
|
-
chat.user "Say hi"
|
|
77
|
-
puts chat.ask
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## 2. Chat file syntax (parser rules)
|
|
83
|
-
|
|
84
|
-
Chat files are parsed by `Chat.parse`.
|
|
85
|
-
|
|
86
|
-
### 2.1 Role headers
|
|
87
|
-
|
|
88
|
-
A **role header** is any line matching:
|
|
89
|
-
|
|
90
|
-
```text
|
|
91
|
-
^[a-z0-9_]+:.*$
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Examples:
|
|
95
|
-
|
|
96
|
-
```text
|
|
97
|
-
user:
|
|
98
|
-
assistant:
|
|
99
|
-
endpoint: nano
|
|
100
|
-
previous_response_id: resp_123
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
There are two forms:
|
|
104
|
-
|
|
105
|
-
1) **Block form**:
|
|
106
|
-
|
|
107
|
-
```text
|
|
108
|
-
user:
|
|
109
|
-
|
|
110
|
-
This is a multi-line user message.
|
|
111
|
-
It continues until the next role header.
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
2) **Inline form** (single line):
|
|
115
|
-
|
|
116
|
-
```text
|
|
117
|
-
endpoint: nano
|
|
118
|
-
model: gpt-5-nano
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Inline headers become their own messages and do not “switch” the role for the following lines (except `previous_response_id`, see below).
|
|
122
|
-
|
|
123
|
-
### 2.2 Special parser protections (to avoid accidental role-splitting)
|
|
124
|
-
|
|
125
|
-
The parser tries hard to avoid splitting a message when content contains colons.
|
|
126
|
-
|
|
127
|
-
Protected regions:
|
|
128
|
-
|
|
129
|
-
- **Markdown code fences**: content between triple backticks is kept in the same message even if it contains `something:` lines.
|
|
130
|
-
- **XML-style blocks**: if the text contains `<tag ...>` and later `</tag>`, the whole block is treated as protected.
|
|
131
|
-
- **Square-bracket protection**: `[[ ... ]]` protects multi-line content that may include role-looking headers.
|
|
132
|
-
- The `[[` and `]]` markers are stripped.
|
|
133
|
-
- **Command output shorthand**: lines like:
|
|
134
|
-
- `shell:-- ls {{{` become `<cmd_output cmd="ls">`
|
|
135
|
-
- `shell:-- ls }}}` become `</cmd_output>`
|
|
136
|
-
|
|
137
|
-
### 2.3 `previous_response_id` nuance
|
|
138
|
-
|
|
139
|
-
`previous_response_id: ...` is special: after an inline `previous_response_id`, the parser resets the next block back to `user`.
|
|
140
|
-
|
|
141
|
-
This makes it convenient to append a new user question *after* a response id marker.
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
## 3. Expansion pipeline: what `LLM.chat` does to a chat
|
|
146
|
-
|
|
147
|
-
When you call `LLM.ask(chat)` or `chat.ask`, Scout-AI first expands the chat via `LLM.chat`.
|
|
148
|
-
|
|
149
|
-
Expansion order (important):
|
|
150
|
-
|
|
151
|
-
1) **Imports** (`import`, `continue`, `last`)
|
|
152
|
-
2) **Clear** (`clear`)
|
|
153
|
-
3) **Clean** (drops empty messages and `skip`)
|
|
154
|
-
4) **Tasks** (`task`, `inline_task`, `exec_task` → jobs)
|
|
155
|
-
5) **Jobs** (`job`, `inline_job` → function_call/function_call_output or file)
|
|
156
|
-
6) **Files** (`file`, `directory`, `image`, `pdf`)
|
|
157
|
-
|
|
158
|
-
After this, backends may do another pass to extract tool definitions.
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## 4. Role reference (chat file / Chat DSL)
|
|
163
|
-
|
|
164
|
-
### 4.1 Standard conversational roles
|
|
165
|
-
|
|
166
|
-
| Role | Meaning |
|
|
167
|
-
|---|---|
|
|
168
|
-
| `system` | System instructions / policy / persona |
|
|
169
|
-
| `user` | User message |
|
|
170
|
-
| `assistant` | Assistant message (usually produced by the model) |
|
|
171
|
-
|
|
172
|
-
### 4.2 Imports and composition
|
|
173
|
-
|
|
174
|
-
Imports are processed by `Chat.imports` during `LLM.chat`.
|
|
175
|
-
|
|
176
|
-
| Role | Effect | Notes |
|
|
177
|
-
|---|---|---|
|
|
178
|
-
| `import` | Inline the referenced chat file(s) | Imports **all** messages from the imported file, except `previous_response_id` |
|
|
179
|
-
| `continue` | Import **only the last non-empty message** from the referenced file | Useful to “continue from the last user/assistant turn” |
|
|
180
|
-
| `last` | Import **only the last non-empty message**, after removing `previous_response_id` | Often used to grab the last assistant answer |
|
|
181
|
-
|
|
182
|
-
Resolution rules for imported paths:
|
|
183
|
-
|
|
184
|
-
- absolute paths work
|
|
185
|
-
- relative paths are resolved relative to the current chat file
|
|
186
|
-
- names may resolve via `Scout.chats[...]`
|
|
187
|
-
|
|
188
|
-
Example:
|
|
189
|
-
|
|
190
|
-
```text
|
|
191
|
-
import: scout-ai/test_stdio
|
|
192
|
-
continue: my_previous_chat
|
|
193
|
-
last: summary_chat
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 4.3 Files and directories
|
|
197
|
-
|
|
198
|
-
Files are processed by `Chat.files` during `LLM.chat`.
|
|
199
|
-
|
|
200
|
-
| Role | Effect |
|
|
201
|
-
|---|---|
|
|
202
|
-
| `file` | Reads the file and inserts it as a tagged `<file name="...">...</file>` inside a `user` message |
|
|
203
|
-
| `directory` | Expands to many `file` insertions for all files under the directory (recursive) |
|
|
204
|
-
| `image` | Resolves to a path (not inlined). Responses backend will upload as base64 when possible |
|
|
205
|
-
| `pdf` | Resolves to a path (not inlined). Responses backend will upload as base64 when possible |
|
|
206
|
-
|
|
207
|
-
Example:
|
|
208
|
-
|
|
209
|
-
```text
|
|
210
|
-
user:
|
|
211
|
-
|
|
212
|
-
Please review these files.
|
|
213
|
-
|
|
214
|
-
directory: lib/scout/llm
|
|
215
|
-
file: README.md
|
|
216
|
-
image: test/data/cat.jpg
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### 4.4 Workflow tools (function calling)
|
|
220
|
-
|
|
221
|
-
There are two related mechanisms:
|
|
222
|
-
|
|
223
|
-
1) **Expose tools** (so the model can call them)
|
|
224
|
-
2) **Run tasks/jobs ahead of time** (so their outputs are available as context)
|
|
225
|
-
|
|
226
|
-
#### `tool` — expose workflow tasks as callable tools
|
|
227
|
-
|
|
228
|
-
`tool: <WorkflowName> [<task_name> [<input1> <input2> ...]]`
|
|
229
|
-
|
|
230
|
-
- If you provide only the workflow name, all exported tasks are available as tools.
|
|
231
|
-
- If you provide a task name, only that task is exposed.
|
|
232
|
-
- If you provide input names, only those inputs are exposed in the JSON schema.
|
|
233
|
-
- You can also provide defaults with `input=value`.
|
|
234
|
-
|
|
235
|
-
Examples:
|
|
236
|
-
|
|
237
|
-
```text
|
|
238
|
-
tool: Baking
|
|
239
|
-
tool: Baking bake_muffin_tray
|
|
240
|
-
tool: Baking bake_muffin_tray blueberries=true
|
|
241
|
-
tool: Baking bake_muffin_tray blueberries
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
#### `introduce` — inject workflow documentation into the chat
|
|
245
|
-
|
|
246
|
-
`introduce: <WorkflowName>` expands into a `user` message containing the workflow documentation (`workflow.documentation`).
|
|
247
|
-
|
|
248
|
-
This is useful when you want the LLM to “understand what the tools do”, not just have access to them.
|
|
249
|
-
|
|
250
|
-
Example:
|
|
251
|
-
|
|
252
|
-
```text
|
|
253
|
-
introduce: Baking
|
|
254
|
-
tool: Baking
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
#### `task`, `inline_task`, `exec_task` — run a workflow job during compilation
|
|
258
|
-
|
|
259
|
-
`task:` lines are executed **before** the model call.
|
|
260
|
-
|
|
261
|
-
Syntax:
|
|
262
|
-
|
|
263
|
-
```text
|
|
264
|
-
task: <WorkflowName> <task_name> key=value key2=value2
|
|
265
|
-
inline_task: <WorkflowName> <task_name> key=value
|
|
266
|
-
exec_task: <WorkflowName> <task_name> key=value
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
Behavior:
|
|
270
|
-
|
|
271
|
-
- `task` → runs the workflow job and replaces itself with a `job:` marker.
|
|
272
|
-
- `inline_task` → runs the workflow job and replaces itself with an `inline_job:` marker.
|
|
273
|
-
- `exec_task` → executes the job immediately and inlines its output into a `user` message.
|
|
274
|
-
|
|
275
|
-
#### `job` / `inline_job` — include a precomputed Step result
|
|
276
|
-
|
|
277
|
-
If you already have a job path (a `Step`), you can embed it:
|
|
278
|
-
|
|
279
|
-
- `inline_job` becomes `file:` (the result is inlined as `<file>`)
|
|
280
|
-
- `job` becomes a pair of messages:
|
|
281
|
-
- `function_call` with `{name, arguments, id}`
|
|
282
|
-
- `function_call_output` with `{id, content}`
|
|
283
|
-
|
|
284
|
-
This is how saved chats can preserve tool-call traces.
|
|
285
|
-
|
|
286
|
-
### 4.5 Knowledge base tools
|
|
287
|
-
|
|
288
|
-
Two ways:
|
|
289
|
-
|
|
290
|
-
#### `association` — register a database from a file path
|
|
291
|
-
|
|
292
|
-
`association: <name> <path> [options...]`
|
|
293
|
-
|
|
294
|
-
Example:
|
|
295
|
-
|
|
296
|
-
```text
|
|
297
|
-
system:
|
|
298
|
-
|
|
299
|
-
Query the knowledge base to answer.
|
|
300
|
-
|
|
301
|
-
association: brothers test/data/person/brothers undirected=true
|
|
302
|
-
association: marriages test/data/person/marriages undirected=true source="=>Alias" target="=>Alias"
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
This dynamically registers the database inside a temporary `KnowledgeBase` and exports tools for it.
|
|
306
|
-
|
|
307
|
-
If a database has fields, an extra tool `<db>_association_details` is also exposed.
|
|
308
|
-
|
|
309
|
-
#### `kb` — load an existing KnowledgeBase directory
|
|
310
|
-
|
|
311
|
-
`kb: <knowledge_base_name_or_path> [db1 db2 ...]`
|
|
312
|
-
|
|
313
|
-
This loads a KB via `KnowledgeBase.load` and exposes tools for all (or selected) databases.
|
|
314
|
-
|
|
315
|
-
### 4.6 MCP tools
|
|
316
|
-
|
|
317
|
-
`mcp: <url_or_stdio> [tool1 tool2 ...]`
|
|
318
|
-
|
|
319
|
-
This loads tool definitions from an MCP server and makes them available as tools.
|
|
320
|
-
|
|
321
|
-
Examples:
|
|
322
|
-
|
|
323
|
-
```text
|
|
324
|
-
mcp: http://localhost:8765
|
|
325
|
-
mcp: stdio 'npx -y @modelcontextprotocol/server-filesystem ${pwd}'
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
If you list tool names after the URL, only those tools are exposed.
|
|
329
|
-
|
|
330
|
-
### 4.7 Options and session control
|
|
331
|
-
|
|
332
|
-
Options are extracted by `Chat.options` and merged into `LLM.ask` options.
|
|
333
|
-
|
|
334
|
-
There are two categories:
|
|
335
|
-
|
|
336
|
-
- **Sticky options**: persist across turns (until overridden)
|
|
337
|
-
- **Transient options**: cleared after an `assistant` message
|
|
338
|
-
|
|
339
|
-
#### Sticky options
|
|
340
|
-
|
|
341
|
-
| Role | Meaning |
|
|
342
|
-
|---|---|
|
|
343
|
-
| `endpoint` | Named endpoint configuration (merged from `~/.scout/etc/AI/<endpoint>`) |
|
|
344
|
-
| `backend` | Backend selector (`responses`, `openai`, `ollama`, `bedrock`, …) |
|
|
345
|
-
| `model` | Model id for the backend |
|
|
346
|
-
| `agent` | Agent name to load (see doc/Agent.md) |
|
|
347
|
-
| `previous_response_id` | Continue a Responses API conversation session |
|
|
348
|
-
|
|
349
|
-
#### Transient options
|
|
350
|
-
|
|
351
|
-
| Role | Meaning |
|
|
352
|
-
|---|---|
|
|
353
|
-
| `format` | Output format: `:json`, `json_object`, or a JSON schema hash |
|
|
354
|
-
| `persist` | Cache control for `LLM.ask` (see `doc/LLM.md`) |
|
|
355
|
-
| `option` | Generic `key value` (cleared after assistant) |
|
|
356
|
-
| `sticky_option` | Generic `key value` (persists across assistant turns) |
|
|
357
|
-
|
|
358
|
-
Examples:
|
|
359
|
-
|
|
360
|
-
```text
|
|
361
|
-
endpoint: nano
|
|
362
|
-
model: gpt-5-nano
|
|
363
|
-
format: json
|
|
364
|
-
|
|
365
|
-
option: websearch true
|
|
366
|
-
sticky_option: endpoint anthropic
|
|
367
|
-
previous_response_id: resp_034e...
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
#### `websearch` (Responses backend)
|
|
371
|
-
|
|
372
|
-
If a message with role `websearch` is present, or if you pass option `websearch: true`, the Responses backend will include the `web_search_preview` tool.
|
|
373
|
-
|
|
374
|
-
Example:
|
|
375
|
-
|
|
376
|
-
```text
|
|
377
|
-
endpoint: deep
|
|
378
|
-
websearch: true
|
|
379
|
-
|
|
380
|
-
user:
|
|
381
|
-
|
|
382
|
-
Find current information about ...
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### 4.8 Maintenance roles
|
|
386
|
-
|
|
387
|
-
| Role | Meaning |
|
|
388
|
-
|---|---|
|
|
389
|
-
| `clear` | Drop all messages *before* the last `clear:` marker |
|
|
390
|
-
| `skip` | Drop this message |
|
|
391
|
-
| `clear_tools` | Remove all previously declared tools (in this compilation) |
|
|
392
|
-
| `clear_associations` | Remove all previously declared associations (in this compilation) |
|
|
393
|
-
|
|
394
|
-
---
|
|
395
|
-
|
|
396
|
-
## 5. Running a chat (Ruby)
|
|
397
|
-
|
|
398
|
-
### 5.1 `ask` vs `chat`
|
|
399
|
-
|
|
400
|
-
- `chat.ask(...)` → returns assistant output (string)
|
|
401
|
-
- `chat.chat(...)` → asks with `return_messages: true` and appends the resulting message trace to the chat
|
|
402
|
-
|
|
403
|
-
### 5.2 JSON helpers
|
|
404
|
-
|
|
405
|
-
```ruby
|
|
406
|
-
chat.format :json
|
|
407
|
-
obj = chat.json
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Or with a schema:
|
|
411
|
-
|
|
412
|
-
```ruby
|
|
413
|
-
obj = chat.json_format({
|
|
414
|
-
name: 'answer',
|
|
415
|
-
type: 'object',
|
|
416
|
-
properties: {content: {type: 'array', items: {type: 'string'}}},
|
|
417
|
-
required: ['content'],
|
|
418
|
-
additionalProperties: false,
|
|
419
|
-
})
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
---
|
|
423
|
-
|
|
424
|
-
## 6. Using chat files from the CLI
|
|
425
|
-
|
|
426
|
-
Chat files are primarily used via:
|
|
427
|
-
|
|
428
|
-
```bash
|
|
429
|
-
scout-ai llm ask --chat my.chat "your question"
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
Behavior:
|
|
433
|
-
|
|
434
|
-
- the file is parsed into messages
|
|
435
|
-
- the model is called
|
|
436
|
-
- the assistant reply (and tool call trace when present) is appended back to the file
|
|
437
|
-
|
|
438
|
-
You can keep typing into the file in an editor and re-run the command.
|
|
439
|
-
|
|
440
|
-
---
|
|
441
|
-
|
|
442
|
-
## 7. Example chat file (with tools + previous_response_id)
|
|
443
|
-
|
|
444
|
-
```text
|
|
445
|
-
user:
|
|
446
|
-
|
|
447
|
-
endpoint: nano
|
|
448
|
-
agent: Baking
|
|
449
|
-
|
|
450
|
-
bake some muffins using bake_muffin_tray, use blueberries
|
|
451
|
-
|
|
452
|
-
function_call: {"name":"bake_muffin_tray","arguments":{"blueberries":true},"id":"call_123"}
|
|
453
|
-
function_call_output: {"name":"bake_muffin_tray","content":"...","id":"call_123"}
|
|
454
|
-
|
|
455
|
-
assistant:
|
|
456
|
-
|
|
457
|
-
Blueberry muffins are in the oven.
|
|
458
|
-
|
|
459
|
-
previous_response_id: resp_034e...
|
|
460
|
-
|
|
461
|
-
Can you also bake one without blueberries?
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
Notes:
|
|
465
|
-
|
|
466
|
-
- `endpoint:` and `agent:` are parsed as their own messages even when written inside a `user:` block.
|
|
467
|
-
- `function_call` / `function_call_output` are how tool traces are persisted in chat logs.
|
|
468
|
-
- `previous_response_id` enables session continuation for the Responses backend.
|
|
469
|
-
|
|
470
|
-
---
|
|
471
|
-
|
|
472
|
-
## 8. Summary
|
|
473
|
-
|
|
474
|
-
Use `Chat` when you want:
|
|
475
|
-
|
|
476
|
-
- a reproducible, append-only conversation artifact on disk
|
|
477
|
-
- a safe way to inline files/directories
|
|
478
|
-
- a declarative way to expose workflow/KB/MCP tools
|
|
479
|
-
- a convenient place to store endpoint/model/options per conversation
|
|
480
|
-
|
|
481
|
-
The key to using chat files effectively is understanding the “control roles” above and the compilation order.
|