@rong/agentscript 0.1.3 → 0.1.5
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 +24 -0
- package/README.md +19 -13
- package/dist/parser/parser.js +34 -11
- package/dist/parser/tokenizer.js +2 -1
- package/dist/providers/llm/anthropic.js +6 -2
- package/dist/providers/llm/ollama.js +9 -2
- package/dist/providers/llm/openai.js +15 -1
- package/dist/providers/llm/shared.js +4 -4
- package/dist/runtime/context.js +2 -2
- package/dist/runtime/evaluator.js +8 -0
- package/dist/runtime/generate.js +22 -6
- package/dist/runtime/shape.js +6 -4
- package/dist/semantic/analyzer.js +20 -3
- package/docs/cn/context-engineering.md +50 -323
- package/docs/cn/final-expression-return.md +5 -5
- package/docs/cn/generate.md +476 -0
- package/docs/cn/language.md +73 -40
- package/docs/cn/use-as.md +225 -0
- package/docs/en/context-engineering.md +51 -269
- package/docs/en/final-expression-return.md +3 -3
- package/docs/en/generate.md +476 -0
- package/docs/en/language.md +73 -40
- package/docs/en/use-as.md +225 -0
- package/examples/changelog.as +2 -2
- package/examples/extract.as +2 -2
- package/examples/review.as +3 -3
- package/examples/summarize.as +2 -2
- package/examples/translate.as +2 -2
- package/package.json +1 -1
- package/tutorials/cli.as +1 -1
- package/tutorials/memory.as +4 -4
- package/tutorials/plan-execute.as +8 -8
- package/tutorials/react.as +9 -9
- package/tutorials/self-improve.as +8 -8
- package/docs/cn/role-label.md +0 -492
|
@@ -1,322 +1,104 @@
|
|
|
1
1
|
# AgentScript Context Engineering
|
|
2
2
|
|
|
3
|
-
This document
|
|
3
|
+
This document is the top-level design map for AgentScript context engineering. It explains why AgentScript exists, what boundaries it enforces, and how the detailed `use ... as ...` and `generate` documents fit together.
|
|
4
4
|
|
|
5
|
-
AgentScript has variables, functions, loops, and agent calls, but its
|
|
5
|
+
AgentScript has variables, functions, loops, tools, memory, and agent calls, but its purpose is not to be a general-purpose programming language. Its purpose is to make prompt context explicit, scoped, typed, traceable, and auditable.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Document structure
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The context engineering design is split into three documents:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **Context Engineering**: this overview; explains the mental model and invariants.
|
|
12
|
+
- **[`use ... as ...`](./use-as.md)**: explains how data is selected as prompt context, how labels work, how budgets are applied, and how scope affects visibility.
|
|
13
|
+
- **[`generate`](./generate.md)**: explains generation sites, prompt construction, agent identity, output contracts, budgets, retries, and trace output.
|
|
12
14
|
|
|
13
|
-
The
|
|
14
|
-
|
|
15
|
-
- **Data**: ordinary variables, JSON values, lists, file imports, tool observations, agent return values.
|
|
16
|
-
- **Context Source**: a prompt context origin declared by `use expr < budget`.
|
|
17
|
-
- **Generation Site**: an LLM call declared by `generate({ input, limit, attempts, debug }) -> shape`.
|
|
18
|
-
- **Boundary**: context visibility boundaries formed by agent, function, and block scopes.
|
|
19
|
-
|
|
20
|
-
## Semantics of `use`
|
|
21
|
-
|
|
22
|
-
`use` is not a variable read or a namespace import. Its meaning is:
|
|
23
|
-
|
|
24
|
-
> Declare a prompt context source in the current scope, so that `generate` calls visible in that scope may include the source's current value in the prompt context.
|
|
25
|
-
|
|
26
|
-
Example:
|
|
27
|
-
|
|
28
|
-
```agentscript
|
|
29
|
-
func answer(question, scratch) {
|
|
30
|
-
use question
|
|
31
|
-
use scratch.summary < 2k
|
|
32
|
-
|
|
33
|
-
generate({
|
|
34
|
-
input: "Answer the question using collected facts"
|
|
35
|
-
limit: 800
|
|
36
|
-
}) -> {
|
|
37
|
-
ok boolean
|
|
38
|
-
text string
|
|
39
|
-
error string
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
```
|
|
15
|
+
The language reference remains the compact syntax reference. These design documents define the intended semantics.
|
|
43
16
|
|
|
44
|
-
|
|
17
|
+
## Core model
|
|
45
18
|
|
|
46
|
-
|
|
19
|
+
AgentScript control flow serves prompt context construction.
|
|
47
20
|
|
|
48
|
-
|
|
21
|
+
Ordinary statements organize data, call tools, call agents, query memory, and update intermediate state. LLM calls happen only through `generate(...) -> { ... }`. A `generate` call sees only context sources explicitly declared with `use` and visible through scope.
|
|
49
22
|
|
|
50
|
-
|
|
51
|
-
main func(input) {
|
|
52
|
-
scratch = []
|
|
53
|
-
use scratch.summary < 2k
|
|
54
|
-
|
|
55
|
-
scratch.add({ fact: "A" })
|
|
56
|
-
scratch.add({ fact: "B" })
|
|
57
|
-
|
|
58
|
-
generate({ input: "Answer from scratch" }) -> {
|
|
59
|
-
text string
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
The `generate` call sees both facts.
|
|
65
|
-
|
|
66
|
-
Rationale:
|
|
67
|
-
|
|
68
|
-
- `use` expresses a context contract, not an assignment.
|
|
69
|
-
- Agent patterns continuously update scratch, plans, and observations.
|
|
70
|
-
- A snapshot-based `use` would require re-declaration before every `generate`, risking stale context.
|
|
23
|
+
The core objects are:
|
|
71
24
|
|
|
72
|
-
|
|
25
|
+
- **Data**: ordinary values such as input, JSON, lists, file contents, tool observations, memory query results, and agent return values.
|
|
26
|
+
- **Context source**: data selected for prompt context by `use expr`, optionally with a budget and label.
|
|
27
|
+
- **Generation site**: one LLM call expressed by `generate({ input, max_output, attempts, temperature, think, strict, debug }) -> shape`.
|
|
28
|
+
- **Boundary**: a visibility boundary formed by an agent, function, or block scope.
|
|
29
|
+
- **Trace**: the audit record explaining which sources were selected, how prompt context was built, and what each generation returned.
|
|
73
30
|
|
|
74
|
-
|
|
31
|
+
## Key invariants
|
|
75
32
|
|
|
76
|
-
|
|
77
|
-
- Imported LLMs / models
|
|
78
|
-
- Imported agent bindings
|
|
79
|
-
- Function bindings
|
|
80
|
-
- Provider URIs, workspace paths, and other execution configuration
|
|
33
|
+
AgentScript should preserve these invariants:
|
|
81
34
|
|
|
82
|
-
|
|
35
|
+
- **No implicit capture**: local variables, tool outputs, memory records, and trace events do not enter prompts unless selected with `use`.
|
|
36
|
+
- **Scoped visibility**: context visibility follows scope. Child scopes can inherit parent context; function and agent calls create independent context boundaries.
|
|
37
|
+
- **Capability isolation**: imported tools, models, agents, memory handles, functions, provider URIs, and runtime configuration are capabilities, not prompt data.
|
|
38
|
+
- **Deferred context resolution**: `use expr` declares a source. The value is resolved when a visible `generate` builds its prompt.
|
|
39
|
+
- **Layered prompts**: prompts distinguish agent identity, selected context, instruction, and output contract.
|
|
40
|
+
- **Auditable traces**: trace output must explain what the LLM call actually saw, including source expressions, labels, budgets, clipping, and generated results.
|
|
83
41
|
|
|
84
|
-
|
|
85
|
-
use Search -- invalid (tool binding)
|
|
86
|
-
use Qwen -- invalid (LLM binding)
|
|
87
|
-
use Worker -- invalid (agent binding)
|
|
88
|
-
use helper -- invalid (function binding)
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Scope as context boundary
|
|
92
|
-
|
|
93
|
-
Scopes in AgentScript control both variable visibility and prompt context visibility.
|
|
42
|
+
## Boundary model
|
|
94
43
|
|
|
95
44
|
### Function boundary
|
|
96
45
|
|
|
97
|
-
Each function call
|
|
46
|
+
Each function call has its own context boundary. A callee does not automatically inherit the caller's selected context. Data must be passed as an argument and selected again when the callee wants it in its own prompt.
|
|
98
47
|
|
|
99
48
|
```agentscript
|
|
100
49
|
func caller(input) {
|
|
101
|
-
use input.goal
|
|
50
|
+
use input.goal as goal
|
|
102
51
|
helper(input)
|
|
103
52
|
}
|
|
104
53
|
|
|
105
54
|
func helper(input) {
|
|
106
|
-
use input.detail
|
|
55
|
+
use input.detail as detail
|
|
107
56
|
generate({ input: "Work on detail" }) -> {
|
|
108
57
|
ok boolean
|
|
109
58
|
}
|
|
110
59
|
}
|
|
111
60
|
```
|
|
112
61
|
|
|
113
|
-
The `generate` inside `helper`
|
|
62
|
+
The `generate` inside `helper` sees `input.detail`, not `caller`'s `input.goal`.
|
|
114
63
|
|
|
115
64
|
### Agent boundary
|
|
116
65
|
|
|
117
|
-
Agent calls create a stronger context
|
|
66
|
+
Agent calls create a stronger boundary. A called agent does not see the caller's prompt context. It sees only its input value and the context selected by its own functions.
|
|
118
67
|
|
|
119
68
|
```agentscript
|
|
120
69
|
result = Worker({
|
|
121
|
-
goal: input.goal
|
|
70
|
+
goal: input.goal,
|
|
122
71
|
previous: results.summary
|
|
123
72
|
})
|
|
124
73
|
```
|
|
125
74
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
This guarantees:
|
|
129
|
-
|
|
130
|
-
- Each agent's prompt contract is independently auditable.
|
|
131
|
-
- Multi-agent composition does not cause implicit context leakage.
|
|
132
|
-
- Sub-agents see only explicitly passed data.
|
|
75
|
+
This keeps multi-agent composition auditable: each agent has its own prompt contract.
|
|
133
76
|
|
|
134
77
|
### Block boundary
|
|
135
78
|
|
|
136
|
-
Blocks
|
|
137
|
-
|
|
138
|
-
```agentscript
|
|
139
|
-
if condition {
|
|
140
|
-
temp = compute(input)
|
|
141
|
-
use temp
|
|
142
|
-
result = generate({ input: "Use temp" }) -> {
|
|
143
|
-
ok boolean
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
`temp` and `use temp` must not leak to the outer scope.
|
|
149
|
-
|
|
150
|
-
### Parent context visibility
|
|
79
|
+
Blocks such as `if`, `repeat`, `loop`, and `for` create child scopes. Context declared inside the block affects `generate` calls inside that block and does not leak upward.
|
|
151
80
|
|
|
152
|
-
|
|
81
|
+
## Prompt layers
|
|
153
82
|
|
|
154
|
-
|
|
83
|
+
A `generate` call is built from four conceptual layers:
|
|
155
84
|
|
|
156
|
-
|
|
85
|
+
1. **Agent identity**: current agent `role`, `description`, and stable behavioral identity.
|
|
86
|
+
2. **Selected context**: visible `use` declarations, rendered with source, label, value, and budget information.
|
|
87
|
+
3. **Instruction**: the per-call task from `generate({ input: ... })`.
|
|
88
|
+
4. **Output contract**: the optional `-> { ... }` shape.
|
|
157
89
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
Describes agent identity and stable behavioral constraints:
|
|
161
|
-
|
|
162
|
-
- Agent name
|
|
163
|
-
- `role`
|
|
164
|
-
- `description`
|
|
165
|
-
|
|
166
|
-
Must not contain execution configuration (provider URIs, workspace paths, tool internals).
|
|
167
|
-
|
|
168
|
-
### Context
|
|
169
|
-
|
|
170
|
-
Comes from `use` declarations visible to the current `generate`.
|
|
171
|
-
|
|
172
|
-
Each context item records:
|
|
173
|
-
|
|
174
|
-
- source expression (e.g. `scratch.summary`)
|
|
175
|
-
- resolved value
|
|
176
|
-
- rendered text
|
|
177
|
-
- budget
|
|
178
|
-
- clipping status
|
|
179
|
-
|
|
180
|
-
Recommended prompt format:
|
|
181
|
-
|
|
182
|
-
```text
|
|
183
|
-
Context:
|
|
184
|
-
[0] question:
|
|
185
|
-
What is AgentScript?
|
|
186
|
-
|
|
187
|
-
[1] scratch.summary:
|
|
188
|
-
[
|
|
189
|
-
{ "fact": "..." }
|
|
190
|
-
]
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
Source labels help models understand context and help humans audit prompts.
|
|
194
|
-
|
|
195
|
-
### Instruction
|
|
196
|
-
|
|
197
|
-
Comes from the `input` field of `generate(...)` options.
|
|
198
|
-
|
|
199
|
-
```agentscript
|
|
200
|
-
generate({ input: "Answer the question using only collected facts" }) -> {
|
|
201
|
-
ok boolean
|
|
202
|
-
text string
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
The instruction is the per-call task. `limit`, `attempts`, and `debug` are local configuration, not prompt context. Error feedback from previous failed attempts is appended to the instruction.
|
|
207
|
-
|
|
208
|
-
### Output contract
|
|
209
|
-
|
|
210
|
-
Comes from the optional `-> { ... }` shape on a `generate` expression.
|
|
211
|
-
|
|
212
|
-
```agentscript
|
|
213
|
-
generate({ input: "Answer" }) -> {
|
|
214
|
-
ok boolean
|
|
215
|
-
text string
|
|
216
|
-
error string
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
The LLM provider and runtime enforce shape compliance as strictly as possible.
|
|
221
|
-
|
|
222
|
-
## Budget semantics
|
|
223
|
-
|
|
224
|
-
`use expr < budget` is a **context item budget**. It limits how much of that source may be rendered into the prompt.
|
|
225
|
-
|
|
226
|
-
`generate({ limit: budget })` is a **generation budget**. It limits output size or the provider's token limit.
|
|
227
|
-
|
|
228
|
-
They have different meanings and must not be confused.
|
|
229
|
-
|
|
230
|
-
Character count is used as an approximation. Future implementations may switch to token-aware budgets without changing the abstraction.
|
|
231
|
-
|
|
232
|
-
## Clipping strategy
|
|
233
|
-
|
|
234
|
-
Context clipping must not simply truncate strings, as that would break JSON and list structure.
|
|
235
|
-
|
|
236
|
-
Strategy:
|
|
237
|
-
|
|
238
|
-
- Strings: may be truncated by character count.
|
|
239
|
-
- Lists: prefer keeping complete items, dropping from the tail.
|
|
240
|
-
- Objects: prefer keeping complete fields, dropping from the tail.
|
|
241
|
-
- Trace: record original size, clipped size, and strategy for each item.
|
|
242
|
-
|
|
243
|
-
## Trace requirements
|
|
244
|
-
|
|
245
|
-
Trace is the primary debugging interface for a context engineering DSL.
|
|
246
|
-
|
|
247
|
-
`use` trace:
|
|
248
|
-
|
|
249
|
-
```json
|
|
250
|
-
{
|
|
251
|
-
"kind": "use",
|
|
252
|
-
"data": {
|
|
253
|
-
"source": "scratch.summary",
|
|
254
|
-
"budget": { "amount": 2, "unit": "k" }
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
`generate` trace:
|
|
260
|
-
|
|
261
|
-
```json
|
|
262
|
-
{
|
|
263
|
-
"kind": "generate",
|
|
264
|
-
"data": {
|
|
265
|
-
"instruction": "Answer from scratch",
|
|
266
|
-
"context": {
|
|
267
|
-
"items": [
|
|
268
|
-
{
|
|
269
|
-
"source": "scratch.summary",
|
|
270
|
-
"value": [{ "fact": "A" }],
|
|
271
|
-
"text": "[...]",
|
|
272
|
-
"budget": { "amount": 2, "unit": "k" },
|
|
273
|
-
"clipped": false
|
|
274
|
-
}
|
|
275
|
-
]
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
This answers:
|
|
282
|
-
|
|
283
|
-
- What did the LLM call actually see?
|
|
284
|
-
- Which context sources were declared but not included?
|
|
285
|
-
- What was clipped?
|
|
286
|
-
- Which expression was the source resolved from?
|
|
287
|
-
- Did caller and callee contexts leak?
|
|
288
|
-
|
|
289
|
-
## The `summary` view
|
|
290
|
-
|
|
291
|
-
`scratch.summary` is a common pattern:
|
|
292
|
-
|
|
293
|
-
```agentscript
|
|
294
|
-
scratch = []
|
|
295
|
-
scratch.add(observation)
|
|
296
|
-
use scratch.summary < 2k
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
It expresses "put the prompt-friendly view of scratch into context." If the implementation provides only a JSON-safe list view rather than a true LLM summary, this should be documented and visible in the trace.
|
|
300
|
-
|
|
301
|
-
## Implementation constraints
|
|
302
|
-
|
|
303
|
-
Future changes must respect:
|
|
304
|
-
|
|
305
|
-
- `generate` does not automatically capture local variables.
|
|
306
|
-
- `use` is a context declaration, not an assignment.
|
|
307
|
-
- `use` values are resolved when `generate` builds the prompt.
|
|
308
|
-
- Function and agent calls form context boundaries.
|
|
309
|
-
- Runtime capabilities must never enter prompt context.
|
|
310
|
-
- Prompts must distinguish system, context, instruction, and output contract layers.
|
|
311
|
-
- Trace must explain every `generate` call's actual context.
|
|
90
|
+
See [`generate`](./generate.md) for the detailed construction rules.
|
|
312
91
|
|
|
313
92
|
## Design checklist
|
|
314
93
|
|
|
315
|
-
Before
|
|
94
|
+
Before changing `use`, scope, context builder, trace, or LLM provider behavior, verify:
|
|
95
|
+
|
|
96
|
+
- Does this let unused data enter a prompt?
|
|
97
|
+
- Does this let caller context pollute a callee?
|
|
98
|
+
- Does this expose tool/model/agent/function bindings as prompt data?
|
|
99
|
+
- Does this preserve source, label, budget, and clipping information for audit?
|
|
100
|
+
- Does this reduce `use` to a snapshot assignment instead of a deferred context source?
|
|
101
|
+
- Does this confuse context budget with generation budget?
|
|
102
|
+
- Does this confuse AgentScript context labels with provider message roles?
|
|
316
103
|
|
|
317
|
-
-
|
|
318
|
-
- Does this change let caller context implicitly pollute callee?
|
|
319
|
-
- Does this change expose tool/model/agent/function bindings as prompt data?
|
|
320
|
-
- Does this change preserve audit information for context sources?
|
|
321
|
-
- Does this change reduce `use` to an ordinary variable snapshot?
|
|
322
|
-
- Does this change confuse context budget with generation budget?
|
|
104
|
+
AgentScript's core value is not another control-flow syntax. Its value is making prompt context source, scope, budget, identity, and final prompt shape explicit and stable.
|
|
@@ -175,11 +175,11 @@ For typical LLM calls, omit `return`:
|
|
|
175
175
|
|
|
176
176
|
```agentscript
|
|
177
177
|
func summarize(content) {
|
|
178
|
-
use content
|
|
178
|
+
use content max 8k
|
|
179
179
|
|
|
180
180
|
generate({
|
|
181
|
-
input: "Summarize the content"
|
|
182
|
-
|
|
181
|
+
input: "Summarize the content",
|
|
182
|
+
max_output: 1000
|
|
183
183
|
}) -> {
|
|
184
184
|
title string
|
|
185
185
|
summary string
|