@rong/agentscript 0.1.0 → 0.1.2

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.
@@ -0,0 +1,197 @@
1
+ # AgentScript Final Expression Return
2
+
3
+ This document describes the implicit return rule for AgentScript functions.
4
+
5
+ ## 1. Basic rule
6
+
7
+ The final top-level expression in a function body can be used as the function return value.
8
+
9
+ ```agentscript
10
+ func answer(input) {
11
+ use input.question
12
+
13
+ generate({ input: "Answer the question" }) -> {
14
+ ok boolean
15
+ answer string
16
+ }
17
+ }
18
+ ```
19
+
20
+ This is equivalent to:
21
+
22
+ ```agentscript
23
+ func answer(input) {
24
+ use input.question
25
+
26
+ return generate({ input: "Answer the question" }) -> {
27
+ ok boolean
28
+ answer string
29
+ }
30
+ }
31
+ ```
32
+
33
+ This rule is called:
34
+
35
+ ```text
36
+ final expression return
37
+ ```
38
+
39
+ ## 2. Expressions that can be implicitly returned
40
+
41
+ The final line can implicitly return these expression forms:
42
+
43
+ ```text
44
+ generate(...) -> shape
45
+ regular function call
46
+ agent call
47
+ variable reference
48
+ field access
49
+ index access
50
+ object literal
51
+ list literal
52
+ ```
53
+
54
+ Examples:
55
+
56
+ ```agentscript
57
+ func run(input) {
58
+ Worker(input)
59
+ }
60
+ ```
61
+
62
+ ```agentscript
63
+ func get_result(result) {
64
+ result.value
65
+ }
66
+ ```
67
+
68
+ ```agentscript
69
+ func observe(action) {
70
+ {
71
+ facts: [action.summary],
72
+ source: action.source
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## 3. Statements that cannot be implicitly returned
78
+
79
+ The following constructs are not expressions and do not participate in final expression return:
80
+
81
+ ```text
82
+ use declaration
83
+ assignment statement
84
+ import
85
+ loop
86
+ repeat
87
+ for
88
+ if/else, which can remain non-expression syntax in early versions
89
+ ```
90
+
91
+ Example:
92
+
93
+ ```agentscript
94
+ func bad(input) {
95
+ use input.question
96
+ }
97
+ ```
98
+
99
+ This function has no return expression. It returns `none`, or the semantic analyzer may report a warning.
100
+
101
+ Assignment also does not return a value:
102
+
103
+ ```agentscript
104
+ func f() {
105
+ x = answer()
106
+ }
107
+ ```
108
+
109
+ To return the assigned value, write:
110
+
111
+ ```agentscript
112
+ func f() {
113
+ x = answer()
114
+ x
115
+ }
116
+ ```
117
+
118
+ ## 4. Explicit `return` takes priority
119
+
120
+ Explicit `return` remains valid and is recommended for complex control flow.
121
+
122
+ ```agentscript
123
+ func answer(input) {
124
+ if input.dry_run {
125
+ return {
126
+ ok: false,
127
+ answer: "dry run"
128
+ }
129
+ }
130
+
131
+ generate({ input: "Answer" }) -> {
132
+ ok boolean
133
+ answer string
134
+ }
135
+ }
136
+ ```
137
+
138
+ ## 5. No return value
139
+
140
+ If a function has no explicit `return` and its final line is not a returnable expression, it returns:
141
+
142
+ ```agentscript
143
+ none
144
+ ```
145
+
146
+ This can also be written explicitly:
147
+
148
+ ```agentscript
149
+ return none
150
+ ```
151
+
152
+ Use this form to express that a function only produces side effects.
153
+
154
+ ## 6. Recommended style
155
+
156
+ For typical LLM calls, omit `return`:
157
+
158
+ ```agentscript
159
+ func summarize(content) {
160
+ use content < 8k
161
+
162
+ generate({
163
+ input: "Summarize the content"
164
+ limit: 1000
165
+ }) -> {
166
+ title string
167
+ summary string
168
+ key_points list[string]
169
+ }
170
+ }
171
+ ```
172
+
173
+ For branches, early exits, and error handling, use explicit `return`:
174
+
175
+ ```agentscript
176
+ func answer(input) {
177
+ if not input.question {
178
+ return {
179
+ ok: false,
180
+ answer: ""
181
+ }
182
+ }
183
+
184
+ use input.question
185
+
186
+ generate({ input: "Answer the question" }) -> {
187
+ ok boolean
188
+ answer string
189
+ }
190
+ }
191
+ ```
192
+
193
+ ## One-sentence definition
194
+
195
+ ```text
196
+ A function returns the value of its final top-level expression when no explicit return is reached.
197
+ ```
@@ -1,6 +1,6 @@
1
1
  # AgentScript Language
2
2
 
3
- This document describes the current AgentScript v1.0.0 language.
3
+ This document describes AgentScript v0.1.x.
4
4
 
5
5
  ## Design principles
6
6
 
@@ -27,11 +27,9 @@ main agent Assistant {
27
27
  question string
28
28
  }) {
29
29
  use input.question
30
- return generate({ input: "Answer the question" }) {
31
- return {
32
- ok boolean
33
- answer string
34
- }
30
+ generate({ input: "Answer the question" }) -> {
31
+ ok boolean
32
+ answer string
35
33
  }
36
34
  }
37
35
  }
@@ -140,13 +138,11 @@ Runtime values are JSON-oriented:
140
138
  Shapes are used for input validation and `generate` output validation:
141
139
 
142
140
  ```agentscript
143
- return generate({ input: "Extract facts" }) {
144
- return {
145
- ok boolean
146
- title string
147
- items list[json]
148
- meta json
149
- }
141
+ generate({ input: "Extract facts" }) -> {
142
+ ok boolean
143
+ title string
144
+ items list[json]
145
+ meta json
150
146
  }
151
147
  ```
152
148
 
@@ -181,7 +177,7 @@ use past_lessons < 2k
181
177
 
182
178
  ## Generate
183
179
 
184
- `generate` calls the current model and requires an `input` instruction plus a return shape.
180
+ `generate` calls the current model and requires an `input` instruction. A return shape is optional.
185
181
 
186
182
  ```agentscript
187
183
  answer = generate({
@@ -189,12 +185,10 @@ answer = generate({
189
185
  limit: 800
190
186
  attempts: 3
191
187
  debug: true
192
- }) {
193
- return {
194
- ok boolean
195
- answer string
196
- reason string
197
- }
188
+ }) -> {
189
+ ok boolean
190
+ answer string
191
+ reason string
198
192
  }
199
193
  ```
200
194
 
@@ -204,7 +198,8 @@ answer = generate({
204
198
  - `limit` is the generation budget (number or `2k` style). Optional.
205
199
  - `attempts` controls retry for JSON parse errors or shape mismatch. Optional, defaults to 1.
206
200
  - `debug` prints the full prompt to stderr. Optional, defaults to false.
207
- - The `return { ... }` block declares the expected output shape.
201
+ - The optional `-> { ... }` block declares the expected output shape.
202
+ - Without `-> { ... }`, the generate output is unconstrained: AgentScript does not add a return schema to the prompt, does not request provider structured output, and does not coerce or validate the returned value.
208
203
  - Provider errors (auth, network, timeout, missing model) fail directly without retry.
209
204
  - Shape validation includes coercion (e.g. `"true"` -> `true`, `"42"` -> `42`).
210
205
 
@@ -371,11 +366,9 @@ import file Config from "./config.json"
371
366
  func answer(input) {
372
367
  use Requirements < 4k
373
368
  use Config
374
- return generate({ input: "Answer from the referenced file." }) {
375
- return {
376
- ok boolean
377
- answer string
378
- }
369
+ generate({ input: "Answer from the referenced file." }) -> {
370
+ ok boolean
371
+ answer string
379
372
  }
380
373
  }
381
374
  ```
@@ -425,7 +418,7 @@ main agent Controller {
425
418
  result = Executor({ goal: input.goal, step: step })
426
419
  results.add(result)
427
420
  }
428
- return results.summary
421
+ results.summary
429
422
  }
430
423
  }
431
424
  ```
@@ -466,7 +459,7 @@ The interpreter is a tree-walking evaluator. There is no IR, bytecode, or compil
466
459
 
467
460
  ## Non-goals
468
461
 
469
- AgentScript v1.0.0 does not provide:
462
+ AgentScript v0.1.x does not provide:
470
463
 
471
464
  - A general workflow engine.
472
465
  - General parallel execution syntax.
@@ -16,14 +16,12 @@ main agent ChangelogWriter {
16
16
  use input.diff_path
17
17
  use diff < 10k
18
18
 
19
- return generate({ input: "Write a changelog from this git diff", limit: 1200 }) {
20
- return {
21
- title string
22
- highlights list[string]
23
- breaking_changes list[string]
24
- fixes list[string]
25
- notes string
26
- }
19
+ generate({ input: "Write a changelog from this git diff", limit: 1200 }) -> {
20
+ title string
21
+ highlights list[string]
22
+ breaking_changes list[string]
23
+ fixes list[string]
24
+ notes string
27
25
  }
28
26
  }
29
27
  }
@@ -17,13 +17,11 @@ main agent ApiExtractor {
17
17
  use input.url
18
18
  use response < 8k
19
19
 
20
- return generate({ input: "Extract normalized data from the API response", limit: 1200 }) {
21
- return {
22
- records list[json]
23
- fields list[string]
24
- warnings list[string]
25
- summary string
26
- }
20
+ generate({ input: "Extract normalized data from the API response", limit: 1200 }) -> {
21
+ records list[json]
22
+ fields list[string]
23
+ warnings list[string]
24
+ summary string
27
25
  }
28
26
  }
29
27
  }
@@ -26,13 +26,11 @@ main agent CodeReviewAssistant {
26
26
  use todos < 4k
27
27
  use fixmes < 4k
28
28
 
29
- return generate({ input: "Turn TODO and FIXME scan results into prioritized repair suggestions", limit: 1200 }) {
30
- return {
31
- summary string
32
- findings list[string]
33
- suggested_fixes list[string]
34
- next_steps list[string]
35
- }
29
+ generate({ input: "Turn TODO and FIXME scan results into prioritized repair suggestions", limit: 1200 }) -> {
30
+ summary string
31
+ findings list[string]
32
+ suggested_fixes list[string]
33
+ next_steps list[string]
36
34
  }
37
35
  }
38
36
  }
@@ -16,13 +16,11 @@ main agent FileSummarizer {
16
16
  use input.path
17
17
  use content < 8k
18
18
 
19
- return generate({ input: "Summarize the file for a busy teammate", limit: 1000 }) {
20
- return {
21
- title string
22
- summary string
23
- key_points list[string]
24
- action_items list[string]
25
- }
19
+ generate({ input: "Summarize the file for a busy teammate", limit: 1000 }) -> {
20
+ title string
21
+ summary string
22
+ key_points list[string]
23
+ action_items list[string]
26
24
  }
27
25
  }
28
26
  }
@@ -21,13 +21,11 @@ main agent MarkdownTranslator {
21
21
  use input.target_language
22
22
  use files < 4k
23
23
 
24
- return generate({ input: "Create a practical markdown translation plan", limit: 1000 }) {
25
- return {
26
- target_language string
27
- files list[string]
28
- glossary_notes list[string]
29
- instructions string
30
- }
24
+ generate({ input: "Create a practical markdown translation plan", limit: 1000 }) -> {
25
+ target_language string
26
+ files list[string]
27
+ glossary_notes list[string]
28
+ instructions string
31
29
  }
32
30
  }
33
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rong/agentscript",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "AgentScript context engineering language runtime",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -47,9 +47,17 @@
47
47
  ],
48
48
  "author": "Rong Zhou",
49
49
  "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/rongzhou/agentscript.git"
53
+ },
54
+ "bugs": {
55
+ "url": "https://github.com/rongzhou/agentscript/issues"
56
+ },
57
+ "homepage": "https://github.com/rongzhou/agentscript#readme",
50
58
  "type": "module",
51
59
  "engines": {
52
- "node": ">=25"
60
+ "node": ">=22.5"
53
61
  },
54
62
  "devDependencies": {
55
63
  "@types/node": "^25.6.2",
package/tutorials/cli.as CHANGED
@@ -12,11 +12,9 @@ main agent {
12
12
  use input.name
13
13
  use input.request
14
14
 
15
- return generate({ input: "Reply to the CLI user by name", limit: 300 }) {
16
- return {
17
- ok boolean
18
- message string
19
- }
15
+ generate({ input: "Reply to the CLI user by name", limit: 300 }) -> {
16
+ ok boolean
17
+ message string
20
18
  }
21
19
  }
22
20
  }
@@ -6,7 +6,7 @@ main agent {
6
6
  description "Return a simple hello world response."
7
7
 
8
8
  main func(input {}) {
9
- return {
9
+ {
10
10
  ok: true,
11
11
  message: "Hello, AgentScript!"
12
12
  }
@@ -10,7 +10,7 @@ main agent MemoryDemo {
10
10
  topic: input.topic
11
11
  })
12
12
 
13
- return Notes.query({
13
+ Notes.query({
14
14
  kind: "note"
15
15
  text: input.topic
16
16
  limit: 3
@@ -44,7 +44,7 @@ main agent PlanAndExecute {
44
44
  }
45
45
  }
46
46
 
47
- return finish(input.goal, results)
47
+ finish(input.goal, results)
48
48
  }
49
49
 
50
50
  func run_step(goal, step, previous) {
@@ -60,7 +60,7 @@ main agent PlanAndExecute {
60
60
  result: result
61
61
  })
62
62
 
63
- return {
63
+ {
64
64
  ok: verdict.ok,
65
65
  reason: verdict.reason,
66
66
  result: {
@@ -75,12 +75,10 @@ main agent PlanAndExecute {
75
75
  use goal
76
76
  use results.summary < 2k
77
77
 
78
- return generate({ input: "Create the final answer from executed steps", limit: 800 }) {
79
- return {
80
- ok boolean
81
- text string
82
- error string
83
- }
78
+ generate({ input: "Create the final answer from executed steps", limit: 800 }) -> {
79
+ ok boolean
80
+ text string
81
+ error string
84
82
  }
85
83
  }
86
84
  }
@@ -95,12 +93,10 @@ agent Planner {
95
93
  use input.problem
96
94
  use input.previous < 1k
97
95
 
98
- return generate({ input: "Create a three step plan", limit: 600 }) {
99
- return {
100
- step1 string
101
- step2 string
102
- step3 string
103
- }
96
+ generate({ input: "Create a three step plan", limit: 600 }) -> {
97
+ step1 string
98
+ step2 string
99
+ step3 string
104
100
  }
105
101
  }
106
102
  }
@@ -125,12 +121,10 @@ agent Executor {
125
121
 
126
122
  use observation
127
123
 
128
- return generate({ input: "Report the result of this step", limit: 500 }) {
129
- return {
130
- ok boolean
131
- output json
132
- error string
133
- }
124
+ generate({ input: "Report the result of this step", limit: 500 }) -> {
125
+ ok boolean
126
+ output json
127
+ error string
134
128
  }
135
129
  }
136
130
  }
@@ -145,11 +139,9 @@ agent Verifier {
145
139
  use input.step
146
140
  use input.result
147
141
 
148
- return generate({ input: "Verify this step result", limit: 300 }) {
149
- return {
150
- ok boolean
151
- reason string
152
- }
142
+ generate({ input: "Verify this step result", limit: 300 }) -> {
143
+ ok boolean
144
+ reason string
153
145
  }
154
146
  }
155
147
  }
@@ -25,18 +25,16 @@ main agent ResearchAgent {
25
25
  done = enough(input.question, scratch)
26
26
  }
27
27
 
28
- return answer(input.question, scratch)
28
+ answer(input.question, scratch)
29
29
  }
30
30
 
31
31
  func reason(question, scratch) {
32
32
  use question
33
33
  use scratch.summary < 1k
34
34
 
35
- return generate({ input: "Choose the next search focus", limit: 300 }) {
36
- return {
37
- focus string
38
- why string
39
- }
35
+ generate({ input: "Choose the next search focus", limit: 300 }) -> {
36
+ focus string
37
+ why string
40
38
  }
41
39
  }
42
40
 
@@ -44,7 +42,7 @@ main agent ResearchAgent {
44
42
  raw_query = Search.query(question, thought)
45
43
  raw_result = Search.search(raw_query)
46
44
 
47
- return {
45
+ {
48
46
  query: raw_query.summary,
49
47
  result: {
50
48
  summary: raw_result.summary,
@@ -62,11 +60,9 @@ main agent ResearchAgent {
62
60
 
63
61
  use raw
64
62
 
65
- return generate({ input: "Summarize the useful observation", limit: 400 }) {
66
- return {
67
- facts list[string]
68
- source string
69
- }
63
+ generate({ input: "Summarize the useful observation", limit: 400 }) -> {
64
+ facts list[string]
65
+ source string
70
66
  }
71
67
  }
72
68
 
@@ -74,25 +70,21 @@ main agent ResearchAgent {
74
70
  use question
75
71
  use scratch.summary < 1k
76
72
 
77
- verdict = generate({ input: "Decide whether the observations are enough", limit: 200 }) {
78
- return {
79
- done boolean
80
- }
73
+ verdict = generate({ input: "Decide whether the observations are enough", limit: 200 }) -> {
74
+ done boolean
81
75
  }
82
76
 
83
- return verdict.done
77
+ verdict.done
84
78
  }
85
79
 
86
80
  func answer(question, scratch) {
87
81
  use question
88
82
  use scratch.summary < 2k
89
83
 
90
- return generate({ input: "Answer using only the observations", limit: 800 }) {
91
- return {
92
- ok boolean
93
- text string
94
- error string
95
- }
84
+ generate({ input: "Answer using only the observations", limit: 800 }) -> {
85
+ ok boolean
86
+ text string
87
+ error string
96
88
  }
97
89
  }
98
90
  }
package/tutorials/repl.as CHANGED
@@ -22,7 +22,7 @@ main agent ReplGuide {
22
22
  }
23
23
  ]
24
24
 
25
- return {
25
+ {
26
26
  ok: true,
27
27
  title: "AgentScript REPL quick start",
28
28
  commands: commands
@@ -21,12 +21,10 @@ main agent SelfImprover {
21
21
  result = generate({
22
22
  input: "Answer the goal using any relevant lessons.",
23
23
  attempts: 3
24
- }) {
25
- return {
26
- ok boolean
27
- answer string
28
- reason string
29
- }
24
+ }) -> {
25
+ ok boolean
26
+ answer string
27
+ reason string
30
28
  }
31
29
 
32
30
  lesson = reflect({
@@ -42,19 +40,17 @@ main agent SelfImprover {
42
40
  ok: result.ok
43
41
  })
44
42
 
45
- return result
43
+ result
46
44
  }
47
45
 
48
46
  func reflect(run) {
49
47
  use run
50
48
 
51
- return generate({
49
+ generate({
52
50
  input: "Extract one durable lesson that could improve a future run.",
53
51
  attempts: 3
54
- }) {
55
- return {
56
- insight string
57
- }
52
+ }) -> {
53
+ insight string
58
54
  }
59
55
  }
60
56
  }