@koi-language/koi 1.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 (85) hide show
  1. package/QUICKSTART.md +89 -0
  2. package/README.md +545 -0
  3. package/examples/actions-demo.koi +177 -0
  4. package/examples/cache-test.koi +29 -0
  5. package/examples/calculator.koi +61 -0
  6. package/examples/clear-registry.js +33 -0
  7. package/examples/clear-registry.koi +30 -0
  8. package/examples/code-introspection-test.koi +149 -0
  9. package/examples/counter.koi +132 -0
  10. package/examples/delegation-test.koi +52 -0
  11. package/examples/directory-import-test.koi +84 -0
  12. package/examples/hello-world-claude.koi +52 -0
  13. package/examples/hello-world.koi +52 -0
  14. package/examples/hello.koi +24 -0
  15. package/examples/mcp-example.koi +70 -0
  16. package/examples/multi-event-handler-test.koi +144 -0
  17. package/examples/new-import-test.koi +89 -0
  18. package/examples/pipeline.koi +162 -0
  19. package/examples/registry-demo.koi +184 -0
  20. package/examples/registry-playbook-demo.koi +162 -0
  21. package/examples/registry-playbook-email-compositor-2.koi +140 -0
  22. package/examples/registry-playbook-email-compositor.koi +140 -0
  23. package/examples/sentiment.koi +90 -0
  24. package/examples/simple.koi +48 -0
  25. package/examples/skill-import-test.koi +76 -0
  26. package/examples/skills/advanced/index.koi +95 -0
  27. package/examples/skills/math-operations.koi +69 -0
  28. package/examples/skills/string-operations.koi +56 -0
  29. package/examples/task-chaining-demo.koi +244 -0
  30. package/examples/test-await.koi +22 -0
  31. package/examples/test-crypto-sha256.koi +196 -0
  32. package/examples/test-delegation.koi +41 -0
  33. package/examples/test-multi-team-routing.koi +258 -0
  34. package/examples/test-no-handler.koi +35 -0
  35. package/examples/test-npm-import.koi +67 -0
  36. package/examples/test-parse.koi +10 -0
  37. package/examples/test-peers-with-team.koi +59 -0
  38. package/examples/test-permissions-fail.koi +20 -0
  39. package/examples/test-permissions.koi +36 -0
  40. package/examples/test-simple-registry.koi +31 -0
  41. package/examples/test-typescript-import.koi +64 -0
  42. package/examples/test-uses-team-syntax.koi +25 -0
  43. package/examples/test-uses-team.koi +31 -0
  44. package/examples/utils/calculator.test.ts +144 -0
  45. package/examples/utils/calculator.ts +56 -0
  46. package/examples/utils/math-helpers.js +50 -0
  47. package/examples/utils/math-helpers.ts +55 -0
  48. package/examples/web-delegation-demo.koi +165 -0
  49. package/package.json +78 -0
  50. package/src/cli/koi.js +793 -0
  51. package/src/compiler/build-optimizer.js +447 -0
  52. package/src/compiler/cache-manager.js +274 -0
  53. package/src/compiler/import-resolver.js +369 -0
  54. package/src/compiler/parser.js +7542 -0
  55. package/src/compiler/transpiler.js +1105 -0
  56. package/src/compiler/typescript-transpiler.js +148 -0
  57. package/src/grammar/koi.pegjs +767 -0
  58. package/src/runtime/action-registry.js +172 -0
  59. package/src/runtime/actions/call-skill.js +45 -0
  60. package/src/runtime/actions/format.js +115 -0
  61. package/src/runtime/actions/print.js +42 -0
  62. package/src/runtime/actions/registry-delete.js +37 -0
  63. package/src/runtime/actions/registry-get.js +37 -0
  64. package/src/runtime/actions/registry-keys.js +33 -0
  65. package/src/runtime/actions/registry-search.js +34 -0
  66. package/src/runtime/actions/registry-set.js +50 -0
  67. package/src/runtime/actions/return.js +31 -0
  68. package/src/runtime/actions/send-message.js +58 -0
  69. package/src/runtime/actions/update-state.js +36 -0
  70. package/src/runtime/agent.js +1368 -0
  71. package/src/runtime/cli-logger.js +205 -0
  72. package/src/runtime/incremental-json-parser.js +201 -0
  73. package/src/runtime/index.js +33 -0
  74. package/src/runtime/llm-provider.js +1372 -0
  75. package/src/runtime/mcp-client.js +1171 -0
  76. package/src/runtime/planner.js +273 -0
  77. package/src/runtime/registry-backends/keyv-sqlite.js +215 -0
  78. package/src/runtime/registry-backends/local.js +260 -0
  79. package/src/runtime/registry.js +162 -0
  80. package/src/runtime/role.js +14 -0
  81. package/src/runtime/router.js +395 -0
  82. package/src/runtime/runtime.js +113 -0
  83. package/src/runtime/skill-selector.js +173 -0
  84. package/src/runtime/skill.js +25 -0
  85. package/src/runtime/team.js +162 -0
@@ -0,0 +1,177 @@
1
+ // ============================================================
2
+ // Koi — Actions Demo
3
+ // Demonstrates playbook-based action system:
4
+ // - update_state: Modify agent state
5
+ // - call_skill: Execute skills
6
+ // - send_message: Send events to peers
7
+ // - return: Return results
8
+ // ============================================================
9
+
10
+ package "demo.koi.actions"
11
+
12
+ role Worker { can execute }
13
+ role LoggerRole { can execute }
14
+
15
+ Agent Logger : LoggerRole {
16
+ llm default = { provider: "openai", model: "gpt-4o-mini", temperature: 0.1, max_tokens: 150 }
17
+
18
+ state {
19
+ logCount: Int = 0
20
+ }
21
+
22
+ on log(args: Json) {
23
+ playbook """
24
+ You are a logger agent. Increment the log count and return confirmation.
25
+
26
+ Current logCount: ${state.logCount}
27
+ Message to log: ${JSON.stringify(args)}
28
+
29
+ Return this JSON with state_updates:
30
+ {
31
+ "state_updates": {
32
+ "logCount": [logCount + 1]
33
+ },
34
+ "logged": true,
35
+ "count": [new logCount]
36
+ }
37
+ """
38
+ }
39
+
40
+ on getLogs(args: Json) {
41
+ playbook """
42
+ Return the current log count.
43
+
44
+ Current logCount: ${state.logCount}
45
+
46
+ Return ONLY:
47
+ {
48
+ "count": ${state.logCount}
49
+ }
50
+ """
51
+ }
52
+ }
53
+
54
+ Agent TaskProcessor : Worker {
55
+ llm default = { provider: "openai", model: "gpt-4o-mini", temperature: 0.2, max_tokens: 300 }
56
+
57
+ state {
58
+ tasksProcessed: Int = 0
59
+ }
60
+
61
+ on processTask(args: Json) {
62
+ playbook """
63
+ You are a task processing agent. Process the incoming task and execute actions.
64
+
65
+ Current state:
66
+ - tasksProcessed: ${state.tasksProcessed}
67
+
68
+ Incoming task: ${JSON.stringify(args)}
69
+
70
+ Your job is to plan and return a list of actions to:
71
+ 1. Update the state (increment tasksProcessed)
72
+ 2. Return the final result
73
+
74
+ Return ONLY this exact JSON structure (no markdown, no explanations):
75
+ {
76
+ "actions": [
77
+ {
78
+ "type": "update_state",
79
+ "updates": {
80
+ "tasksProcessed": [current tasksProcessed + 1]
81
+ }
82
+ },
83
+ {
84
+ "type": "return",
85
+ "data": {
86
+ "success": true,
87
+ "task": "[task description from args.task]",
88
+ "tasksProcessed": [new count]
89
+ }
90
+ }
91
+ ]
92
+ }
93
+
94
+ Example if args = {"task": "analyze data", "priority": "high"}:
95
+ {
96
+ "actions": [
97
+ {
98
+ "type": "update_state",
99
+ "updates": {
100
+ "tasksProcessed": 1
101
+ }
102
+ },
103
+ {
104
+ "type": "return",
105
+ "data": {
106
+ "success": true,
107
+ "task": "analyze data",
108
+ "tasksProcessed": 1
109
+ }
110
+ }
111
+ ]
112
+ }
113
+ """
114
+ }
115
+
116
+ on getStatus(args: Json) {
117
+ playbook """
118
+ Return the current status of the task processor.
119
+
120
+ Current state:
121
+ - tasksProcessed: ${state.tasksProcessed}
122
+
123
+ Return ONLY:
124
+ {
125
+ "tasksProcessed": ${state.tasksProcessed}
126
+ }
127
+ """
128
+ }
129
+ }
130
+
131
+ Team LoggingTeam {
132
+ logger = Logger
133
+ processor = TaskProcessor
134
+ }
135
+
136
+ Agent Orchestrator : Worker {
137
+ uses Team LoggingTeam
138
+
139
+ on start(args: Json) {
140
+ console.log("🎯 Actions Demo Starting...")
141
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
142
+
143
+ // Process first task
144
+ console.log("\n📋 Processing Task 1: Analyze User Data")
145
+ const task1 =
146
+ await send peers.event("processTask").role(Worker).any()({
147
+ task: "analyze user data",
148
+ priority: "high"
149
+ }) timeout 15s
150
+ console.log("✓ Task 1 result:", task1)
151
+
152
+ // Process second task
153
+ console.log("\n📋 Processing Task 2: Generate Report")
154
+ const task2 =
155
+ await send peers.event("processTask").role(Worker).any()({
156
+ task: "generate monthly report",
157
+ priority: "medium"
158
+ }) timeout 15s
159
+ console.log("✓ Task 2 result:", task2)
160
+
161
+ // Get processor status
162
+ console.log("\n📊 Getting processor status...")
163
+ const status =
164
+ await send peers.event("getStatus").role(Worker).any()({}) timeout 10s
165
+ console.log("✓ Status:", status)
166
+
167
+ console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
168
+ return {
169
+ message: "Actions demo complete ✓",
170
+ summary: {
171
+ tasksProcessed: status.tasksProcessed
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ run Orchestrator.start({})
@@ -0,0 +1,29 @@
1
+ // Cache Test Example
2
+ package "test.cache"
3
+
4
+ role Worker { can execute }
5
+
6
+ Agent TextTranslator : Worker {
7
+ llm default = { provider: "openai", model: "gpt-4o-mini" }
8
+
9
+ on translate(args: Json) {
10
+ playbook """
11
+ Translate this text to the target language: ${args.text}
12
+ Target language: ${args.language}
13
+ Return JSON with translated text.
14
+ """
15
+ }
16
+ }
17
+
18
+ Agent WordAnalyzer : Worker {
19
+ llm default = { provider: "openai", model: "gpt-4o-mini" }
20
+
21
+ on analyze(args: Json) {
22
+ playbook """
23
+ Analyze this text and count words: ${args.text}
24
+ Return JSON with word count and analysis.
25
+ """
26
+ }
27
+ }
28
+
29
+ run TextTranslator.translate({ text: "hello", language: "spanish" })
@@ -0,0 +1,61 @@
1
+ // ============================================================
2
+ // Koi — Calculator Example
3
+ // Simple calculator with multiple operations (procedural code only)
4
+ // ============================================================
5
+
6
+ package "demo.koi.calculator"
7
+
8
+ role Worker { can execute }
9
+
10
+ // All handlers use procedural code (no playbooks)
11
+ Agent Calculator : Worker {
12
+ on add(args: Json) {
13
+ const a = args.a
14
+ const b = args.b
15
+ return { result: a + b, operation: "add" }
16
+ }
17
+
18
+ on multiply(args: Json) {
19
+ const a = args.a
20
+ const b = args.b
21
+ return { result: a * b, operation: "multiply" }
22
+ }
23
+
24
+ on divide(args: Json) {
25
+ const a = args.a
26
+ const b = args.b
27
+
28
+ if b == 0 {
29
+ return { error: "Division by zero", operation: "divide" }
30
+ }
31
+
32
+ return { result: a / b, operation: "divide" }
33
+ }
34
+ }
35
+
36
+ Team CalcTeam {
37
+ calc = Calculator
38
+ }
39
+
40
+ Agent Orchestrator : Worker {
41
+ uses Team CalcTeam
42
+
43
+ on start(args: Json) {
44
+ const sum =
45
+ await send peers.event("add").role(Worker).any()({ a: 10, b: 5 }) timeout 2s
46
+
47
+ const product =
48
+ await send peers.event("multiply").role(Worker).any()({ a: 10, b: 5 }) timeout 2s
49
+
50
+ const quotient =
51
+ await send peers.event("divide").role(Worker).any()({ a: 10, b: 5 }) timeout 2s
52
+
53
+ return {
54
+ sum: sum,
55
+ product: product,
56
+ quotient: quotient
57
+ }
58
+ }
59
+ }
60
+
61
+ run Orchestrator.start({})
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Clear Registry - Delete all data from the registry
4
+ import { registry } from '../src/runtime/index.js';
5
+
6
+ async function clearRegistry() {
7
+ console.log("⚠️ WARNING: Clearing all registry data...");
8
+ console.log("");
9
+
10
+ // Show stats before clearing
11
+ const statsBefore = await registry.stats();
12
+ console.log(" Current entries:", statsBefore.count);
13
+ console.log(" Storage:", statsBefore.file);
14
+ console.log("");
15
+
16
+ // Clear the registry
17
+ await registry.clear();
18
+
19
+ console.log("✅ Registry cleared successfully!");
20
+ console.log("");
21
+
22
+ // Show stats after clearing
23
+ const statsAfter = await registry.stats();
24
+ console.log(" Entries remaining:", statsAfter.count);
25
+ console.log("");
26
+
27
+ process.exit(0);
28
+ }
29
+
30
+ clearRegistry().catch((error) => {
31
+ console.error("❌ Error clearing registry:", error.message);
32
+ process.exit(1);
33
+ });
@@ -0,0 +1,30 @@
1
+ // Clear Registry - Delete all data from the registry
2
+ package "clear.registry"
3
+
4
+ role Admin { can execute }
5
+
6
+ Agent Cleaner : Admin {
7
+ on clearAll(args: Json) {
8
+ console.log("⚠️ WARNING: Clearing all registry data...")
9
+
10
+ // Show current stats before clearing
11
+ const statsBefore = await registry.stats()
12
+ console.log(" Current entries:", statsBefore.count)
13
+ console.log(" Storage:", statsBefore.file)
14
+ console.log("")
15
+
16
+ // Clear the registry
17
+ await registry.clear()
18
+
19
+ console.log("✅ Registry cleared successfully!")
20
+
21
+ // Show stats after clearing
22
+ const statsAfter = await registry.stats()
23
+ console.log(" Entries remaining:", statsAfter.count)
24
+ console.log("")
25
+
26
+ return { success: true, clearedCount: statsBefore.count }
27
+ }
28
+ }
29
+
30
+ run Cleaner.clearAll({})
@@ -0,0 +1,149 @@
1
+ package "demo.code.introspection"
2
+
3
+ role Calculator { can calculate }
4
+ role Coordinator { can coordinate }
5
+
6
+ // Agent con event handler que tiene código (no playbook)
7
+ // El sistema debe hacer introspección para generar affordance
8
+ Agent MathProcessor : Calculator {
9
+ llm default = {
10
+ provider: "openai",
11
+ model: "gpt-4o-mini",
12
+ temperature: 0.1
13
+ }
14
+
15
+ // Event handler con código Koi (sin playbook)
16
+ // El sistema hará introspección del código para generar affordance
17
+ // Este handler suma todos los números en el array
18
+ on calculateSum(args: Json) {
19
+ const numbers = args.numbers
20
+
21
+ // Procesar números y sumarlos
22
+ const result = await send peers.event("sumArray").role(Calculator).any()({
23
+ data: numbers
24
+ }) timeout 5s
25
+
26
+ return {
27
+ operation: "sum",
28
+ result: result
29
+ }
30
+ }
31
+
32
+ // Event handler que multiplica todos los números
33
+ on calculateProduct(args: Json) {
34
+ const numbers = args.numbers
35
+
36
+ // Multiplicar los números usando delegación
37
+ const result = await send peers.event("multiplyArray").role(Calculator).any()({
38
+ data: numbers
39
+ }) timeout 5s
40
+
41
+ return {
42
+ operation: "product",
43
+ result: result
44
+ }
45
+ }
46
+
47
+ // Event handler con playbook (para comparar)
48
+ on calculateAverage(args: Json) {
49
+ playbook """
50
+ Calculate the average of ${JSON.stringify(args.numbers)}
51
+
52
+ Sum all numbers and divide by count.
53
+ Return: { "operation": "average", "result": <value> }
54
+ """
55
+ }
56
+ }
57
+
58
+ Team MathTeam {
59
+ processor = MathProcessor
60
+ }
61
+
62
+ // Coordinator que delega basándose en affordances
63
+ Agent Coordinator : Coordinator {
64
+ llm default = {
65
+ provider: "openai",
66
+ model: "gpt-4o-mini",
67
+ temperature: 0.1
68
+ }
69
+
70
+ uses Team MathTeam
71
+
72
+ on process(args: Json) {
73
+ playbook """
74
+ Process this math request: ${JSON.stringify(args)}
75
+
76
+ Available operations (delegate to Calculator role):
77
+ - Calculate sum/total of numbers
78
+ - Calculate product/multiplication of numbers
79
+ - Calculate average/mean of numbers
80
+
81
+ Determine the intent and delegate with an action:
82
+ {
83
+ "actions": [{
84
+ "title": "Calculating...",
85
+ "intent": "<your interpretation of what math operation is needed>",
86
+ "data": { "numbers": ${JSON.stringify(args.numbers)} }
87
+ }]
88
+ }
89
+ """
90
+ }
91
+ }
92
+
93
+ Team CoordinatorTeam {
94
+ coordinator = Coordinator
95
+ }
96
+
97
+ Agent Main : Coordinator {
98
+ uses Team CoordinatorTeam
99
+
100
+ on start(args: Json) {
101
+ console.log("╔════════════════════════════════════════════╗")
102
+ console.log("║ Code Introspection Test ║")
103
+ console.log("║ Event handlers with source code ║")
104
+ console.log("╚════════════════════════════════════════════╝\n")
105
+
106
+ // Test 1: Request sum (should route to calculateSum)
107
+ console.log("📋 Test 1: Calculate the total")
108
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
109
+
110
+ const sumResult =
111
+ await send peers.event("process").role(Coordinator).any()({
112
+ operation: "calculate the total of these numbers",
113
+ numbers: [5, 10, 15, 20]
114
+ }) timeout 30s
115
+
116
+ console.log("Result:", JSON.stringify(sumResult, null, 2))
117
+
118
+ // Test 2: Request product (should route to calculateProduct)
119
+ console.log("\n📋 Test 2: Multiply all numbers")
120
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
121
+
122
+ const productResult =
123
+ await send peers.event("process").role(Coordinator).any()({
124
+ operation: "multiply all the numbers together",
125
+ numbers: [2, 3, 4, 5]
126
+ }) timeout 30s
127
+
128
+ console.log("Result:", JSON.stringify(productResult, null, 2))
129
+
130
+ // Test 3: Request average (should route to calculateAverage with playbook)
131
+ console.log("\n📋 Test 3: Find the average")
132
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
133
+
134
+ const avgResult =
135
+ await send peers.event("process").role(Coordinator).any()({
136
+ operation: "find the average value",
137
+ numbers: [10, 20, 30, 40, 50]
138
+ }) timeout 30s
139
+
140
+ console.log("Result:", JSON.stringify(avgResult, null, 2))
141
+
142
+ return {
143
+ success: true,
144
+ tests_completed: 3
145
+ }
146
+ }
147
+ }
148
+
149
+ run Main.start({})
@@ -0,0 +1,132 @@
1
+ // ============================================================
2
+ // Koi — Counter Example
3
+ // Simple stateful agent that counts using playbooks
4
+ // ============================================================
5
+
6
+ package "demo.koi.counter"
7
+
8
+ role Worker { can execute }
9
+
10
+ Agent Counter : Worker {
11
+ llm default = { provider: "openai", model: "gpt-4o-mini", temperature: 0.1, max_tokens: 200 }
12
+
13
+ state {
14
+ count: Int = 0
15
+ }
16
+
17
+ on increment(args: Json) {
18
+ playbook """
19
+ You are a counter agent. Increment the internal counter by 1 and return the new value.
20
+
21
+ Current state: state.count = ${state.count}
22
+
23
+ Your task:
24
+ 1. Calculate the new count by adding 1 to the current count
25
+ 2. Return a JSON response with BOTH the result AND the state update
26
+
27
+ Return ONLY this exact JSON structure (no markdown, no explanations):
28
+ {
29
+ "state_updates": {
30
+ "count": [new count value after incrementing]
31
+ },
32
+ "count": [new count value after incrementing]
33
+ }
34
+
35
+ Example: If current count is 5, return:
36
+ {
37
+ "state_updates": { "count": 6 },
38
+ "count": 6
39
+ }
40
+ """
41
+ }
42
+
43
+ on get(args: Json) {
44
+ playbook """
45
+ You are a counter agent. Return the current counter value without modifying it.
46
+
47
+ Current state: state.count = ${state.count}
48
+
49
+ Return ONLY this exact JSON structure (no markdown, no explanations):
50
+ {
51
+ "count": ${state.count}
52
+ }
53
+ """
54
+ }
55
+
56
+ on reset(args: Json) {
57
+ playbook """
58
+ You are a counter agent. Reset the counter to zero.
59
+
60
+ Current state: state.count = ${state.count}
61
+
62
+ Your task:
63
+ 1. Reset the counter to 0
64
+ 2. Return a JSON response with BOTH the result AND the state update
65
+
66
+ Return ONLY this exact JSON structure (no markdown, no explanations):
67
+ {
68
+ "state_updates": {
69
+ "count": 0
70
+ },
71
+ "count": 0
72
+ }
73
+ """
74
+ }
75
+
76
+ on incrementBy(args: Json) {
77
+ playbook """
78
+ You are a counter agent. Increment the counter by a specific amount.
79
+
80
+ Current state: state.count = ${state.count}
81
+ Amount to increment: args.amount = ${args.amount || 1}
82
+
83
+ Your task:
84
+ 1. Calculate the new count by adding args.amount to the current count
85
+ 2. Return a JSON response with BOTH the result AND the state update
86
+
87
+ Return ONLY this exact JSON structure (no markdown, no explanations):
88
+ {
89
+ "state_updates": {
90
+ "count": [new count value]
91
+ },
92
+ "count": [new count value],
93
+ "incremented": [amount that was added]
94
+ }
95
+ """
96
+ }
97
+ }
98
+
99
+ Team CounterTeam {
100
+ counter = Counter
101
+ }
102
+
103
+ Agent Orchestrator : Worker {
104
+ uses Team CounterTeam
105
+
106
+ on start(args: Json) {
107
+ console.log("🔢 Counter Test Starting...")
108
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
109
+
110
+ const r1 =
111
+ await send peers.event("increment").role(Worker).any()({}) timeout 5s
112
+ console.log("✓ After increment 1:", r1)
113
+
114
+ const r2 =
115
+ await send peers.event("increment").role(Worker).any()({}) timeout 5s
116
+ console.log("✓ After increment 2:", r2)
117
+
118
+ const r3 =
119
+ await send peers.event("increment").role(Worker).any()({}) timeout 5s
120
+ console.log("✓ After increment 3:", r3)
121
+
122
+ const current =
123
+ await send peers.event("get").role(Worker).any()({}) timeout 5s
124
+ console.log("✓ Current value:", current)
125
+
126
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
127
+
128
+ return { message: "Counter test complete ✓", final: current }
129
+ }
130
+ }
131
+
132
+ run Orchestrator.start({})
@@ -0,0 +1,52 @@
1
+ package "test.delegation"
2
+
3
+ role Worker { can execute }
4
+
5
+ // Simple translator agent
6
+ Agent Translator : Worker {
7
+ llm default = { provider: "openai", model: "gpt-4o-mini" }
8
+
9
+ on translate(args: Json) {
10
+ playbook """
11
+ Translate "${args.text}" to ${args.language}.
12
+ Return JSON: { "translated": "translated text here" }
13
+ """
14
+ }
15
+ }
16
+
17
+ // Simple counter agent
18
+ Agent WordCounter : Worker {
19
+ llm default = { provider: "openai", model: "gpt-4o-mini" }
20
+
21
+ on count(args: Json) {
22
+ playbook """
23
+ Count words in: "${args.text}"
24
+ Return JSON: { "wordCount": number }
25
+ """
26
+ }
27
+ }
28
+
29
+ // Orchestrator that chains tasks
30
+ Agent Orchestrator : Worker {
31
+ llm default = { provider: "openai", model: "gpt-4o-mini" }
32
+
33
+ on processText(args: Json) {
34
+ playbook """
35
+ Task: Translate "${args.text}" to Spanish, then count the words.
36
+
37
+ Create a plan with 2 actions:
38
+ 1. Translate the text to Spanish
39
+ 2. Count the words in the translation
40
+
41
+ Return JSON with actions array:
42
+ {
43
+ "actions": [
44
+ { "intent": "translate to spanish", "data": { "text": "${args.text}", "language": "spanish" } },
45
+ { "intent": "count words", "data": { "text": "\${previousResult.translated}" } }
46
+ ]
47
+ }
48
+ """
49
+ }
50
+ }
51
+
52
+ run Orchestrator.processText({ text: "hello world" })