@rong/agentscript 0.1.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.
- package/CHANGELOG.md +22 -0
- package/INSTALL.md +92 -0
- package/LICENSE +21 -0
- package/README.md +246 -0
- package/dist/ast/constants.js +1 -0
- package/dist/ast/format.js +41 -0
- package/dist/ast/types.js +1 -0
- package/dist/bin/agentscript.js +234 -0
- package/dist/bin/input.js +19 -0
- package/dist/bin/repl.js +290 -0
- package/dist/index.js +26 -0
- package/dist/parser/errors.js +8 -0
- package/dist/parser/parser.js +661 -0
- package/dist/parser/tokenizer.js +246 -0
- package/dist/providers/llm/anthropic.js +36 -0
- package/dist/providers/llm/index.js +3 -0
- package/dist/providers/llm/ollama.js +19 -0
- package/dist/providers/llm/openai.js +31 -0
- package/dist/providers/llm/protocol.js +45 -0
- package/dist/providers/llm/shared.js +147 -0
- package/dist/providers/llm/types.js +1 -0
- package/dist/providers/llm/uri.js +24 -0
- package/dist/providers/memory/file.js +44 -0
- package/dist/providers/memory/host.js +66 -0
- package/dist/providers/memory/index.js +1 -0
- package/dist/providers/memory/shared.js +56 -0
- package/dist/providers/memory/sqlite.js +98 -0
- package/dist/providers/mock/index.js +32 -0
- package/dist/providers/tools/env.js +11 -0
- package/dist/providers/tools/file.js +99 -0
- package/dist/providers/tools/host.js +34 -0
- package/dist/providers/tools/http.js +40 -0
- package/dist/providers/tools/index.js +2 -0
- package/dist/providers/tools/scheme.js +16 -0
- package/dist/providers/tools/shared.js +92 -0
- package/dist/providers/tools/shell.js +80 -0
- package/dist/runtime/context.js +160 -0
- package/dist/runtime/errors.js +14 -0
- package/dist/runtime/evaluator.js +276 -0
- package/dist/runtime/generate.js +175 -0
- package/dist/runtime/guards.js +39 -0
- package/dist/runtime/input.js +38 -0
- package/dist/runtime/interpreter.js +314 -0
- package/dist/runtime/json.js +59 -0
- package/dist/runtime/loader.js +146 -0
- package/dist/runtime/scope.js +47 -0
- package/dist/runtime/shape.js +132 -0
- package/dist/runtime/trace.js +54 -0
- package/dist/runtime/truth.js +13 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/uri.js +10 -0
- package/dist/semantic/analyzer.js +519 -0
- package/dist/semantic/diagnostics.js +16 -0
- package/dist/utils/assert.js +3 -0
- package/docs/cn/context-engineering.md +389 -0
- package/docs/cn/language.md +478 -0
- package/docs/design-history/v0-design.md +365 -0
- package/docs/design-history/v0-implement.md +274 -0
- package/docs/design-history/v1-design.md +323 -0
- package/docs/design-history/v1-implement.md +267 -0
- package/docs/design-history/v2-design.md +387 -0
- package/docs/design-history/v2-implement.md +399 -0
- package/docs/en/context-engineering.md +332 -0
- package/docs/en/language.md +478 -0
- package/examples/changelog.as +29 -0
- package/examples/extract.as +29 -0
- package/examples/review.as +38 -0
- package/examples/summarize.as +28 -0
- package/examples/translate.as +33 -0
- package/package.json +59 -0
- package/tutorials/cli.as +22 -0
- package/tutorials/helloworld.as +14 -0
- package/tutorials/memory.as +19 -0
- package/tutorials/plan-execute.as +155 -0
- package/tutorials/react.as +98 -0
- package/tutorials/repl.as +31 -0
- package/tutorials/self-improve.as +60 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# AgentScript Context Engineering
|
|
2
|
+
|
|
3
|
+
本文档说明 AgentScript 中 `use`、作用域和 `generate` 的核心设计含义。这个概念不属于某个特定版本,而是 AgentScript 区别于普通编程语言的基础语义。
|
|
4
|
+
|
|
5
|
+
AgentScript 表面上有变量、函数、循环和 Agent 调用,但它的主要目标不是成为通用编程语言,而是提供一种可审计、可组合、显式的 prompt context engineering DSL。
|
|
6
|
+
|
|
7
|
+
后续开发涉及 `use`、scope、context builder、trace 或 prompt 结构时,应优先参考本文档。若实现细节与本文不一致,应先判断是实现尚未跟上设计,还是本文需要更新。
|
|
8
|
+
|
|
9
|
+
## 核心定位
|
|
10
|
+
|
|
11
|
+
AgentScript 的控制流服务于 prompt context 构建。
|
|
12
|
+
|
|
13
|
+
普通语句负责组织数据、调用工具、调用 Agent 和更新中间状态。LLM 调用只能通过 `generate(...) { return ... }` 发生,而 `generate` 能看到的上下文必须由 `use` 显式声明。
|
|
14
|
+
|
|
15
|
+
AgentScript 的核心对象是:
|
|
16
|
+
|
|
17
|
+
- `Data`:普通变量、JSON、list、file import、tool observation 和 Agent 返回值。
|
|
18
|
+
- `Context Source`:由 `use expr < budget` 声明的 prompt context 来源。
|
|
19
|
+
- `Generation Site`:由 `generate({ input, limit, attempts, debug }) { return shape }` 声明的一次 LLM 调用。
|
|
20
|
+
- `Boundary`:由 Agent、function 和 block scope 形成的 context 可见性边界。
|
|
21
|
+
|
|
22
|
+
## `use` 的语义
|
|
23
|
+
|
|
24
|
+
`use` 不是普通编程语言中的变量读取,也不是把变量导入某个命名空间。`use` 的含义是:
|
|
25
|
+
|
|
26
|
+
> 在当前作用域声明一个 prompt context source,使后续在该作用域内可见的 `generate` 可以把该 source 的值放入 prompt context。
|
|
27
|
+
|
|
28
|
+
例如:
|
|
29
|
+
|
|
30
|
+
```agentscript
|
|
31
|
+
func answer(question, scratch) {
|
|
32
|
+
use question
|
|
33
|
+
use scratch.summary < 2k
|
|
34
|
+
|
|
35
|
+
return generate({
|
|
36
|
+
input: "Answer the question using collected facts"
|
|
37
|
+
limit: 800
|
|
38
|
+
}) {
|
|
39
|
+
return {
|
|
40
|
+
ok boolean
|
|
41
|
+
text string
|
|
42
|
+
error string
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
这里 `question` 和 `scratch.summary` 是本次 `generate` 的显式 context source。没有被 `use` 的局部变量不应自动进入 prompt。
|
|
49
|
+
|
|
50
|
+
## `use` 应是延迟求值的 context source
|
|
51
|
+
|
|
52
|
+
目标语义是:
|
|
53
|
+
|
|
54
|
+
> `use expr < budget` 声明的是 `expr` 这个 context source,而不是立即复制 `expr` 的当前值。真正构建 prompt 时,应在 `generate` 执行点解析该 source 的当前值。
|
|
55
|
+
|
|
56
|
+
因此,下面的程序应让 `generate` 看到更新后的 `scratch.summary`:
|
|
57
|
+
|
|
58
|
+
```agentscript
|
|
59
|
+
main func(input) {
|
|
60
|
+
scratch = []
|
|
61
|
+
use scratch.summary < 2k
|
|
62
|
+
|
|
63
|
+
scratch.add({ fact: "A" })
|
|
64
|
+
scratch.add({ fact: "B" })
|
|
65
|
+
|
|
66
|
+
return generate({ input: "Answer from scratch" }) {
|
|
67
|
+
return {
|
|
68
|
+
text string
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
设计理由:
|
|
75
|
+
|
|
76
|
+
- `use` 表达的是 context contract,而不是一次普通赋值。
|
|
77
|
+
- Agent 常见模式会持续更新 scratch、plan、observations。
|
|
78
|
+
- 如果 `use` 是快照,用户必须在每个 `generate` 前重复声明,容易造成陈旧 context。
|
|
79
|
+
- 延迟求值更符合 context engineering 中“声明可见源,在调用点构建 prompt”的直觉。
|
|
80
|
+
|
|
81
|
+
实现上可以把 `use` 存为 `expr + declaring scope + budget`,在 `generate` 构建 context 时再求值。
|
|
82
|
+
|
|
83
|
+
## `use` 与 prompt 暴露边界
|
|
84
|
+
|
|
85
|
+
默认情况下,LLM 不应看到当前函数内的全部变量。
|
|
86
|
+
|
|
87
|
+
以下内容只有被显式 `use` 后才可进入 prompt context:
|
|
88
|
+
|
|
89
|
+
- 用户输入。
|
|
90
|
+
- 中间结果。
|
|
91
|
+
- scratch 或 memory-like 数据。
|
|
92
|
+
- 工具 observation。
|
|
93
|
+
- imported file 的内容。
|
|
94
|
+
- 其他 Agent 的返回值。
|
|
95
|
+
|
|
96
|
+
以下 runtime capability 不应作为 prompt context:
|
|
97
|
+
|
|
98
|
+
- imported tool。
|
|
99
|
+
- imported llm/model。
|
|
100
|
+
- imported agent binding。
|
|
101
|
+
- function binding。
|
|
102
|
+
- provider URI、workspace path 等执行配置。
|
|
103
|
+
|
|
104
|
+
例如,下面应被语义分析禁止:
|
|
105
|
+
|
|
106
|
+
```agentscript
|
|
107
|
+
use Search
|
|
108
|
+
use Qwen
|
|
109
|
+
use Worker
|
|
110
|
+
use helper
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
这条规则的目的不是类型洁癖,而是防止把执行能力或 runtime 配置误当作数据暴露给 LLM。
|
|
114
|
+
|
|
115
|
+
## Scope 是 context boundary
|
|
116
|
+
|
|
117
|
+
AgentScript 中的作用域不仅是变量可见性规则,也是 prompt context 可见性规则。
|
|
118
|
+
|
|
119
|
+
### Function boundary
|
|
120
|
+
|
|
121
|
+
函数调用应创建独立 context boundary。
|
|
122
|
+
|
|
123
|
+
```agentscript
|
|
124
|
+
func caller(input) {
|
|
125
|
+
use input.goal
|
|
126
|
+
return helper(input)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func helper(input) {
|
|
130
|
+
use input.detail
|
|
131
|
+
return generate({ input: "Work on detail" }) {
|
|
132
|
+
return {
|
|
133
|
+
ok boolean
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`helper` 内部的 `generate` 不应自动继承 `caller` 的 `use input.goal`,除非该数据作为参数传入并在 `helper` 内显式 `use`。
|
|
140
|
+
|
|
141
|
+
推荐原则:
|
|
142
|
+
|
|
143
|
+
- function 的 prompt context 由 function 自己声明。
|
|
144
|
+
- function 返回值不携带 prompt context。
|
|
145
|
+
- caller 的 `use` 不应隐式污染 callee。
|
|
146
|
+
|
|
147
|
+
### Agent boundary
|
|
148
|
+
|
|
149
|
+
Agent 调用是更强的 context boundary。
|
|
150
|
+
|
|
151
|
+
```agentscript
|
|
152
|
+
result = Worker({
|
|
153
|
+
goal: input.goal
|
|
154
|
+
previous: results.summary
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`Worker` 不应自动看到 Controller 的 context。Controller 必须通过参数显式传入必要数据,Worker 再用自己的 `use` 声明 prompt context。
|
|
159
|
+
|
|
160
|
+
这保证:
|
|
161
|
+
|
|
162
|
+
- 每个 Agent 的 prompt contract 独立可审计。
|
|
163
|
+
- 多 Agent 组合不会发生隐式 context 泄露。
|
|
164
|
+
- 子 Agent 只看到调用者明确传入的数据。
|
|
165
|
+
|
|
166
|
+
### Block boundary
|
|
167
|
+
|
|
168
|
+
`if`、`repeat`、`loop`、`for` 等 block 可以创建子作用域。子作用域内声明的 `use` 只应影响该子作用域内可见的 `generate`。
|
|
169
|
+
|
|
170
|
+
```agentscript
|
|
171
|
+
if condition {
|
|
172
|
+
temp = compute(input)
|
|
173
|
+
use temp
|
|
174
|
+
result = generate({ input: "Use temp" }) {
|
|
175
|
+
return {
|
|
176
|
+
ok boolean
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`temp` 和 `use temp` 不应泄漏到外层作用域。
|
|
183
|
+
|
|
184
|
+
### Parent context visibility
|
|
185
|
+
|
|
186
|
+
如果一个 block 内的 `generate` 处在某个父作用域之下,它可以看到父作用域声明的 context source。可见顺序应从外到内稳定排列,便于 trace 和 prompt 审计。
|
|
187
|
+
|
|
188
|
+
## Context 构建模型
|
|
189
|
+
|
|
190
|
+
一次 `generate` 的 prompt 应由四层组成。
|
|
191
|
+
|
|
192
|
+
### System
|
|
193
|
+
|
|
194
|
+
System 层描述 Agent identity 和稳定行为约束,例如:
|
|
195
|
+
|
|
196
|
+
- Agent name。
|
|
197
|
+
- `role`。
|
|
198
|
+
- `description`。
|
|
199
|
+
|
|
200
|
+
System 层不应包含 provider URI、workspace path、tool implementation detail 或其它执行配置。
|
|
201
|
+
|
|
202
|
+
### Context
|
|
203
|
+
|
|
204
|
+
Context 层来自当前 `generate` 可见的 `use` 声明。
|
|
205
|
+
|
|
206
|
+
每个 context item 应包含:
|
|
207
|
+
|
|
208
|
+
- source expression,例如 `scratch.summary`。
|
|
209
|
+
- resolved value。
|
|
210
|
+
- rendered text。
|
|
211
|
+
- budget。
|
|
212
|
+
- clipping status。
|
|
213
|
+
|
|
214
|
+
推荐 prompt 形态:
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
Context:
|
|
218
|
+
[0] question:
|
|
219
|
+
What is AgentScript?
|
|
220
|
+
|
|
221
|
+
[1] scratch.summary:
|
|
222
|
+
[
|
|
223
|
+
{ "fact": "..." }
|
|
224
|
+
]
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
source label 有助于模型理解 context,也有助于人类审计。
|
|
228
|
+
|
|
229
|
+
### Instruction
|
|
230
|
+
|
|
231
|
+
Instruction 层来自 `generate(...)` 参数对象中的 `input` 字段。
|
|
232
|
+
|
|
233
|
+
```agentscript
|
|
234
|
+
generate({ input: "Answer the question using only collected facts" }) {
|
|
235
|
+
return {
|
|
236
|
+
ok boolean
|
|
237
|
+
text string
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Instruction 是本次 LLM 调用的局部任务,不应混入长期 context。
|
|
243
|
+
|
|
244
|
+
`limit`、`attempts` 和 `debug` 是 `generate` 的局部配置,不属于 prompt context。只有当上一次输出不是 JSON 或不满足 shape 时,runtime 才会在下一次尝试中把错误反馈附加到 instruction。
|
|
245
|
+
|
|
246
|
+
### Output contract
|
|
247
|
+
|
|
248
|
+
Output contract 来自 `return shape`。
|
|
249
|
+
|
|
250
|
+
```agentscript
|
|
251
|
+
return {
|
|
252
|
+
ok boolean
|
|
253
|
+
text string
|
|
254
|
+
error string
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
LLM provider 和 runtime 应尽可能强制输出满足该 shape。
|
|
259
|
+
|
|
260
|
+
## Budget 语义
|
|
261
|
+
|
|
262
|
+
`use expr < budget` 是 context item budget。
|
|
263
|
+
|
|
264
|
+
```agentscript
|
|
265
|
+
use scratch.summary < 2k
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
它限制的是该 context source 渲染进 prompt 的大小,不是整个 LLM 调用的输出预算。
|
|
269
|
+
|
|
270
|
+
`generate({ limit: budget }) { ... }` 是 generation budget。
|
|
271
|
+
|
|
272
|
+
```agentscript
|
|
273
|
+
return generate({
|
|
274
|
+
input: "Summarize"
|
|
275
|
+
limit: 500
|
|
276
|
+
}) {
|
|
277
|
+
return {
|
|
278
|
+
text string
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
它限制的是本次生成的输出规模或 provider token limit。
|
|
284
|
+
|
|
285
|
+
两者语义不同,不应混用。
|
|
286
|
+
|
|
287
|
+
可以先用字符数近似 context budget,但文档和 trace 必须明确实际裁剪策略。若未来切换到 token budget,不应改变 `use` 的抽象含义。
|
|
288
|
+
|
|
289
|
+
## Clipping 策略
|
|
290
|
+
|
|
291
|
+
Context clipping 不应只做简单字符串截断,因为这会破坏 JSON/list 结构。
|
|
292
|
+
|
|
293
|
+
推荐策略:
|
|
294
|
+
|
|
295
|
+
- string 可以按字符截断。
|
|
296
|
+
- list 应优先保留完整 item。
|
|
297
|
+
- object 应优先保留完整字段。
|
|
298
|
+
- 超限时 trace 应记录原始大小、裁剪后大小和裁剪策略。
|
|
299
|
+
|
|
300
|
+
如果暂时使用简单字符串截断,必须在 trace 中标记 `clipped: true`,并在文档中说明这是早期实现策略。
|
|
301
|
+
|
|
302
|
+
## Trace 要求
|
|
303
|
+
|
|
304
|
+
Trace 是 context engineering DSL 的核心调试接口。
|
|
305
|
+
|
|
306
|
+
`use` trace 应记录声明信息:
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"kind": "use",
|
|
311
|
+
"data": {
|
|
312
|
+
"source": "scratch.summary",
|
|
313
|
+
"budget": { "amount": 2, "unit": "k" }
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
`generate` trace 应记录实际构建出的 context:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"kind": "generate",
|
|
323
|
+
"data": {
|
|
324
|
+
"instruction": "Answer from scratch",
|
|
325
|
+
"context": {
|
|
326
|
+
"items": [
|
|
327
|
+
{
|
|
328
|
+
"source": "scratch.summary",
|
|
329
|
+
"value": [{ "fact": "A" }],
|
|
330
|
+
"text": "[...]",
|
|
331
|
+
"budget": { "amount": 2, "unit": "k" },
|
|
332
|
+
"clipped": false
|
|
333
|
+
}
|
|
334
|
+
]
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
这使开发者可以回答:
|
|
341
|
+
|
|
342
|
+
- 本次 LLM 调用到底看到了什么?
|
|
343
|
+
- 哪些 context source 被声明但没有进入当前 generate?
|
|
344
|
+
- 哪些 context 被裁剪?
|
|
345
|
+
- context 是从哪个表达式解析出来的?
|
|
346
|
+
- caller 和 callee 的 context 是否发生了意外污染?
|
|
347
|
+
|
|
348
|
+
## `summary` view 的含义
|
|
349
|
+
|
|
350
|
+
`scratch.summary` 是 AgentScript 中常见的 context engineering 写法。
|
|
351
|
+
|
|
352
|
+
```agentscript
|
|
353
|
+
scratch = []
|
|
354
|
+
scratch.add(observation)
|
|
355
|
+
use scratch.summary < 2k
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
它表达的是“把 scratch 的 prompt-friendly view 放入 context”。如果实现中 `summary` 只是 JSON-safe list view,而不是真正的 LLM 摘要,应在文档和 trace 中明确。
|
|
359
|
+
|
|
360
|
+
推荐长期方向:
|
|
361
|
+
|
|
362
|
+
- `summary` 表示适合 prompt 的紧凑视图。
|
|
363
|
+
- `summary` 不应暴露 runtime resource binding。
|
|
364
|
+
- `summary` 可以结合 clipping 策略保留最有用的完整 item。
|
|
365
|
+
|
|
366
|
+
## 实现约束
|
|
367
|
+
|
|
368
|
+
为了避免把 AgentScript 误实现成普通编程语言,后续改动应遵守以下约束:
|
|
369
|
+
|
|
370
|
+
- `generate` 不自动捕获局部变量。
|
|
371
|
+
- `use` 是 context declaration,不是普通赋值。
|
|
372
|
+
- `use` 的值应在 `generate` 构建 prompt 时解析。
|
|
373
|
+
- function 和 Agent 调用应形成 context boundary。
|
|
374
|
+
- runtime capability 不应进入 prompt context。
|
|
375
|
+
- prompt 中应区分 system、context、instruction 和 output contract。
|
|
376
|
+
- trace 必须能解释每次 `generate` 的实际 context。
|
|
377
|
+
|
|
378
|
+
## 设计检查清单
|
|
379
|
+
|
|
380
|
+
修改 `use`、scope、context builder、trace 或 LLM provider 前,应检查:
|
|
381
|
+
|
|
382
|
+
- 这个改动是否让未 `use` 的数据进入了 prompt?
|
|
383
|
+
- 这个改动是否让 caller context 隐式污染 callee?
|
|
384
|
+
- 这个改动是否把 tool/model/agent/function binding 当作数据暴露给 LLM?
|
|
385
|
+
- 这个改动是否保留了 context source 的可审计信息?
|
|
386
|
+
- 这个改动是否让 `use` 退化成普通变量快照?
|
|
387
|
+
- 这个改动是否混淆了 context budget 和 generation budget?
|
|
388
|
+
|
|
389
|
+
AgentScript 的核心价值不是多一种控制流语法,而是让 prompt context 的来源、范围、预算和最终形态都变得显式、稳定、可审计。
|