language-operator 0.0.1 → 0.1.31
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/.rubocop.yml +125 -0
- data/CHANGELOG.md +88 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +284 -0
- data/LICENSE +229 -21
- data/Makefile +82 -0
- data/README.md +3 -11
- data/Rakefile +63 -0
- data/bin/aictl +7 -0
- data/completions/_aictl +232 -0
- data/completions/aictl.bash +121 -0
- data/completions/aictl.fish +114 -0
- data/docs/architecture/agent-runtime.md +585 -0
- data/docs/dsl/SCHEMA_VERSION.md +250 -0
- data/docs/dsl/agent-reference.md +604 -0
- data/docs/dsl/best-practices.md +1078 -0
- data/docs/dsl/chat-endpoints.md +895 -0
- data/docs/dsl/constraints.md +671 -0
- data/docs/dsl/mcp-integration.md +1177 -0
- data/docs/dsl/webhooks.md +932 -0
- data/docs/dsl/workflows.md +744 -0
- data/lib/language_operator/agent/base.rb +110 -0
- data/lib/language_operator/agent/executor.rb +440 -0
- data/lib/language_operator/agent/instrumentation.rb +54 -0
- data/lib/language_operator/agent/metrics_tracker.rb +183 -0
- data/lib/language_operator/agent/safety/ast_validator.rb +272 -0
- data/lib/language_operator/agent/safety/audit_logger.rb +104 -0
- data/lib/language_operator/agent/safety/budget_tracker.rb +175 -0
- data/lib/language_operator/agent/safety/content_filter.rb +93 -0
- data/lib/language_operator/agent/safety/manager.rb +207 -0
- data/lib/language_operator/agent/safety/rate_limiter.rb +150 -0
- data/lib/language_operator/agent/safety/safe_executor.rb +127 -0
- data/lib/language_operator/agent/scheduler.rb +183 -0
- data/lib/language_operator/agent/telemetry.rb +116 -0
- data/lib/language_operator/agent/web_server.rb +610 -0
- data/lib/language_operator/agent/webhook_authenticator.rb +226 -0
- data/lib/language_operator/agent.rb +149 -0
- data/lib/language_operator/cli/commands/agent.rb +1205 -0
- data/lib/language_operator/cli/commands/cluster.rb +371 -0
- data/lib/language_operator/cli/commands/install.rb +404 -0
- data/lib/language_operator/cli/commands/model.rb +266 -0
- data/lib/language_operator/cli/commands/persona.rb +393 -0
- data/lib/language_operator/cli/commands/quickstart.rb +22 -0
- data/lib/language_operator/cli/commands/status.rb +143 -0
- data/lib/language_operator/cli/commands/system.rb +772 -0
- data/lib/language_operator/cli/commands/tool.rb +537 -0
- data/lib/language_operator/cli/commands/use.rb +47 -0
- data/lib/language_operator/cli/errors/handler.rb +180 -0
- data/lib/language_operator/cli/errors/suggestions.rb +176 -0
- data/lib/language_operator/cli/formatters/code_formatter.rb +77 -0
- data/lib/language_operator/cli/formatters/log_formatter.rb +288 -0
- data/lib/language_operator/cli/formatters/progress_formatter.rb +49 -0
- data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
- data/lib/language_operator/cli/formatters/table_formatter.rb +163 -0
- data/lib/language_operator/cli/formatters/value_formatter.rb +113 -0
- data/lib/language_operator/cli/helpers/cluster_context.rb +62 -0
- data/lib/language_operator/cli/helpers/cluster_validator.rb +101 -0
- data/lib/language_operator/cli/helpers/editor_helper.rb +58 -0
- data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +167 -0
- data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
- data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +74 -0
- data/lib/language_operator/cli/helpers/schedule_builder.rb +108 -0
- data/lib/language_operator/cli/helpers/user_prompts.rb +69 -0
- data/lib/language_operator/cli/main.rb +236 -0
- data/lib/language_operator/cli/templates/tools/generic.yaml +66 -0
- data/lib/language_operator/cli/wizards/agent_wizard.rb +246 -0
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +588 -0
- data/lib/language_operator/client/base.rb +214 -0
- data/lib/language_operator/client/config.rb +136 -0
- data/lib/language_operator/client/cost_calculator.rb +37 -0
- data/lib/language_operator/client/mcp_connector.rb +123 -0
- data/lib/language_operator/client.rb +19 -0
- data/lib/language_operator/config/cluster_config.rb +101 -0
- data/lib/language_operator/config/tool_patterns.yaml +57 -0
- data/lib/language_operator/config/tool_registry.rb +96 -0
- data/lib/language_operator/config.rb +138 -0
- data/lib/language_operator/dsl/adapter.rb +124 -0
- data/lib/language_operator/dsl/agent_context.rb +90 -0
- data/lib/language_operator/dsl/agent_definition.rb +427 -0
- data/lib/language_operator/dsl/chat_endpoint_definition.rb +115 -0
- data/lib/language_operator/dsl/config.rb +119 -0
- data/lib/language_operator/dsl/context.rb +50 -0
- data/lib/language_operator/dsl/execution_context.rb +47 -0
- data/lib/language_operator/dsl/helpers.rb +109 -0
- data/lib/language_operator/dsl/http.rb +184 -0
- data/lib/language_operator/dsl/mcp_server_definition.rb +73 -0
- data/lib/language_operator/dsl/parameter_definition.rb +124 -0
- data/lib/language_operator/dsl/registry.rb +36 -0
- data/lib/language_operator/dsl/schema.rb +1102 -0
- data/lib/language_operator/dsl/shell.rb +125 -0
- data/lib/language_operator/dsl/tool_definition.rb +112 -0
- data/lib/language_operator/dsl/webhook_authentication.rb +114 -0
- data/lib/language_operator/dsl/webhook_definition.rb +106 -0
- data/lib/language_operator/dsl/workflow_definition.rb +259 -0
- data/lib/language_operator/dsl.rb +161 -0
- data/lib/language_operator/errors.rb +60 -0
- data/lib/language_operator/kubernetes/client.rb +279 -0
- data/lib/language_operator/kubernetes/resource_builder.rb +194 -0
- data/lib/language_operator/loggable.rb +47 -0
- data/lib/language_operator/logger.rb +141 -0
- data/lib/language_operator/retry.rb +123 -0
- data/lib/language_operator/retryable.rb +132 -0
- data/lib/language_operator/templates/README.md +23 -0
- data/lib/language_operator/templates/examples/agent_synthesis.tmpl +115 -0
- data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
- data/lib/language_operator/templates/schema/.gitkeep +0 -0
- data/lib/language_operator/templates/schema/CHANGELOG.md +93 -0
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +452 -0
- data/lib/language_operator/tool_loader.rb +242 -0
- data/lib/language_operator/validators.rb +170 -0
- data/lib/language_operator/version.rb +1 -1
- data/lib/language_operator.rb +65 -3
- data/requirements/tasks/challenge.md +9 -0
- data/requirements/tasks/iterate.md +36 -0
- data/requirements/tasks/optimize.md +21 -0
- data/requirements/tasks/tag.md +5 -0
- data/test_agent_dsl.rb +108 -0
- metadata +507 -20
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
# Agent Runtime Architecture
|
|
2
|
+
|
|
3
|
+
This document explains how synthesized agent code becomes a running agent in the Language Operator system.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Language Operator follows this flow:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Natural Language Description
|
|
11
|
+
↓
|
|
12
|
+
Operator synthesizes Ruby DSL code
|
|
13
|
+
↓
|
|
14
|
+
Stores in ConfigMap "<agent-name>-code"
|
|
15
|
+
↓
|
|
16
|
+
Creates Pod with ConfigMap mounted
|
|
17
|
+
↓
|
|
18
|
+
Ruby runtime loads and executes agent
|
|
19
|
+
↓
|
|
20
|
+
Agent executes workflow using tools and models
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Components
|
|
24
|
+
|
|
25
|
+
### 1. Synthesis Phase (Go Operator)
|
|
26
|
+
|
|
27
|
+
The Kubernetes operator receives an `LanguageAgent` custom resource:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
apiVersion: language-operator.io/v1alpha1
|
|
31
|
+
kind: LanguageAgent
|
|
32
|
+
metadata:
|
|
33
|
+
name: email-summarizer
|
|
34
|
+
spec:
|
|
35
|
+
description: "Check my inbox every hour and send me a summary"
|
|
36
|
+
model: claude-3-5-sonnet
|
|
37
|
+
schedule:
|
|
38
|
+
cron: "0 * * * *"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The operator:
|
|
42
|
+
1. Sends description to LLM for synthesis
|
|
43
|
+
2. LLM generates Ruby DSL code
|
|
44
|
+
3. Stores code in ConfigMap `email-summarizer-code` with key `agent.rb`
|
|
45
|
+
|
|
46
|
+
**Example synthesized code:**
|
|
47
|
+
```ruby
|
|
48
|
+
agent "email-summarizer" do
|
|
49
|
+
description "Check inbox hourly and send summary"
|
|
50
|
+
|
|
51
|
+
objectives [
|
|
52
|
+
"Connect to Gmail",
|
|
53
|
+
"Fetch unread messages from the last hour",
|
|
54
|
+
"Summarize key points",
|
|
55
|
+
"Send summary email"
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
workflow do
|
|
59
|
+
step :fetch_emails,
|
|
60
|
+
tool: "gmail",
|
|
61
|
+
instruction: "Get unread emails from last hour"
|
|
62
|
+
|
|
63
|
+
step :summarize,
|
|
64
|
+
instruction: "Create bullet-point summary of emails"
|
|
65
|
+
|
|
66
|
+
step :send_summary,
|
|
67
|
+
tool: "gmail",
|
|
68
|
+
instruction: "Send summary to user"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
constraints do
|
|
72
|
+
max_iterations 50
|
|
73
|
+
timeout "5m"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Pod Creation Phase (Go Operator)
|
|
79
|
+
|
|
80
|
+
The operator creates a Pod for the agent:
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
apiVersion: v1
|
|
84
|
+
kind: Pod
|
|
85
|
+
metadata:
|
|
86
|
+
name: email-summarizer-xyz123
|
|
87
|
+
namespace: default
|
|
88
|
+
spec:
|
|
89
|
+
containers:
|
|
90
|
+
- name: agent
|
|
91
|
+
image: language-operator/agent-runtime:v0.1.0
|
|
92
|
+
env:
|
|
93
|
+
- name: AGENT_NAME
|
|
94
|
+
value: "email-summarizer"
|
|
95
|
+
- name: AGENT_CODE_PATH
|
|
96
|
+
value: "/config/agent.rb"
|
|
97
|
+
- name: MODEL_ENDPOINTS
|
|
98
|
+
value: "https://api.anthropic.com/v1/messages"
|
|
99
|
+
- name: MCP_SERVERS
|
|
100
|
+
value: "http://gmail-tool.default.svc.cluster.local:3000"
|
|
101
|
+
- name: WORKSPACE_PATH
|
|
102
|
+
value: "/workspace"
|
|
103
|
+
- name: AGENT_MODE
|
|
104
|
+
value: "scheduled"
|
|
105
|
+
volumeMounts:
|
|
106
|
+
- name: agent-code
|
|
107
|
+
mountPath: /config
|
|
108
|
+
readOnly: true
|
|
109
|
+
- name: workspace
|
|
110
|
+
mountPath: /workspace
|
|
111
|
+
volumes:
|
|
112
|
+
- name: agent-code
|
|
113
|
+
configMap:
|
|
114
|
+
name: email-summarizer-code
|
|
115
|
+
- name: workspace
|
|
116
|
+
persistentVolumeClaim:
|
|
117
|
+
claimName: email-summarizer-workspace
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. Runtime Initialization Phase (Ruby)
|
|
121
|
+
|
|
122
|
+
**Entrypoint:** `lib/language_operator/agent.rb`
|
|
123
|
+
|
|
124
|
+
The container starts with this entrypoint:
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
#!/usr/bin/env ruby
|
|
128
|
+
|
|
129
|
+
require 'language_operator'
|
|
130
|
+
|
|
131
|
+
# Start the agent runtime
|
|
132
|
+
LanguageOperator::Agent.run
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**What happens in `Agent.run`:**
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
module LanguageOperator
|
|
139
|
+
module Agent
|
|
140
|
+
def self.run
|
|
141
|
+
# Load configuration (environment variables)
|
|
142
|
+
config = Client::Config.new
|
|
143
|
+
|
|
144
|
+
# Create agent instance
|
|
145
|
+
agent = Base.new(config)
|
|
146
|
+
|
|
147
|
+
# Start execution
|
|
148
|
+
agent.run
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 4. Configuration Loading
|
|
155
|
+
|
|
156
|
+
**File:** `lib/language_operator/client/config.rb`
|
|
157
|
+
|
|
158
|
+
The configuration system reads environment variables:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
module LanguageOperator
|
|
162
|
+
module Client
|
|
163
|
+
class Config
|
|
164
|
+
def self.from_env
|
|
165
|
+
{
|
|
166
|
+
model_endpoints: parse_endpoints(ENV['MODEL_ENDPOINTS']),
|
|
167
|
+
mcp_servers: parse_endpoints(ENV['MCP_SERVERS']),
|
|
168
|
+
workspace_path: ENV['WORKSPACE_PATH'] || '/workspace',
|
|
169
|
+
agent_mode: ENV['AGENT_MODE'] || 'autonomous'
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def self.parse_endpoints(value)
|
|
176
|
+
return [] unless value
|
|
177
|
+
value.split(',').map(&:strip)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 5. Agent Execution
|
|
185
|
+
|
|
186
|
+
**File:** `lib/language_operator/agent/base.rb`
|
|
187
|
+
|
|
188
|
+
The agent base class handles execution mode:
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
module LanguageOperator
|
|
192
|
+
module Agent
|
|
193
|
+
class Base
|
|
194
|
+
def initialize(config)
|
|
195
|
+
@config = config
|
|
196
|
+
@workspace = Workspace.new(config.workspace_path)
|
|
197
|
+
@executor = Executor.new(config)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def run
|
|
201
|
+
case @config.agent_mode
|
|
202
|
+
when 'autonomous'
|
|
203
|
+
run_autonomous
|
|
204
|
+
when 'scheduled'
|
|
205
|
+
run_scheduled
|
|
206
|
+
else
|
|
207
|
+
raise "Unknown agent mode: #{@config.agent_mode}"
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
212
|
+
|
|
213
|
+
def run_autonomous
|
|
214
|
+
# Continuous execution loop
|
|
215
|
+
loop do
|
|
216
|
+
@executor.run_cycle
|
|
217
|
+
sleep 1
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def run_scheduled
|
|
222
|
+
# Wait for schedule trigger, then execute once
|
|
223
|
+
@executor.run_cycle
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### 6. DSL Code Loading (Future Implementation)
|
|
231
|
+
|
|
232
|
+
**Note:** This integration is planned but not yet implemented. The DSL infrastructure exists but needs to be wired into the agent runtime.
|
|
233
|
+
|
|
234
|
+
**Planned implementation:**
|
|
235
|
+
|
|
236
|
+
```ruby
|
|
237
|
+
def run_autonomous
|
|
238
|
+
# Load synthesized agent code
|
|
239
|
+
agent_code_path = ENV['AGENT_CODE_PATH'] || '/config/agent.rb'
|
|
240
|
+
|
|
241
|
+
if File.exist?(agent_code_path)
|
|
242
|
+
# Load the DSL file
|
|
243
|
+
LanguageOperator::Dsl.load_agent_file(agent_code_path)
|
|
244
|
+
|
|
245
|
+
# Get agent definition from registry
|
|
246
|
+
agent_name = ENV['AGENT_NAME']
|
|
247
|
+
agent_def = LanguageOperator::Dsl.agent_registry.get(agent_name)
|
|
248
|
+
|
|
249
|
+
if agent_def&.workflow
|
|
250
|
+
# Execute the defined workflow
|
|
251
|
+
@executor.execute_workflow(agent_def)
|
|
252
|
+
else
|
|
253
|
+
# Fall back to autonomous mode
|
|
254
|
+
@executor.run_cycle
|
|
255
|
+
end
|
|
256
|
+
else
|
|
257
|
+
# No synthesized code, run generic autonomous mode
|
|
258
|
+
@executor.run_cycle
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**The DSL loader** (`lib/language_operator/dsl.rb:109-121`):
|
|
264
|
+
|
|
265
|
+
```ruby
|
|
266
|
+
module LanguageOperator
|
|
267
|
+
module Dsl
|
|
268
|
+
def self.load_agent_file(path)
|
|
269
|
+
context = AgentContext.new
|
|
270
|
+
code = File.read(path)
|
|
271
|
+
context.instance_eval(code, path)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**The registry** (`lib/language_operator/dsl/agent_context.rb:47-88`):
|
|
278
|
+
|
|
279
|
+
```ruby
|
|
280
|
+
module LanguageOperator
|
|
281
|
+
module Dsl
|
|
282
|
+
class AgentRegistry
|
|
283
|
+
def initialize
|
|
284
|
+
@agents = {}
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def register(name, definition)
|
|
288
|
+
@agents[name.to_s] = definition
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def get(name)
|
|
292
|
+
@agents[name.to_s]
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def all
|
|
296
|
+
@agents.values
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def self.agent_registry
|
|
301
|
+
@agent_registry ||= AgentRegistry.new
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### 7. Workflow Execution
|
|
308
|
+
|
|
309
|
+
**File:** `lib/language_operator/agent/executor.rb`
|
|
310
|
+
|
|
311
|
+
The executor runs the agent's workflow:
|
|
312
|
+
|
|
313
|
+
```ruby
|
|
314
|
+
module LanguageOperator
|
|
315
|
+
module Agent
|
|
316
|
+
class Executor
|
|
317
|
+
def execute_workflow(agent_definition)
|
|
318
|
+
# Extract workflow from agent definition
|
|
319
|
+
workflow = agent_definition.workflow
|
|
320
|
+
|
|
321
|
+
# Execute each step
|
|
322
|
+
workflow.steps.each do |step|
|
|
323
|
+
execute_step(step)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def execute_step(step)
|
|
328
|
+
case step.type
|
|
329
|
+
when :tool
|
|
330
|
+
call_tool(step.tool, step.instruction)
|
|
331
|
+
when :analysis
|
|
332
|
+
analyze(step.instruction)
|
|
333
|
+
else
|
|
334
|
+
# Generic LLM call
|
|
335
|
+
call_llm(step.instruction)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Environment Variables
|
|
344
|
+
|
|
345
|
+
The agent runtime uses these environment variables (injected by the operator):
|
|
346
|
+
|
|
347
|
+
| Variable | Description | Example |
|
|
348
|
+
|----------|-------------|---------|
|
|
349
|
+
| `AGENT_NAME` | Name of the agent | `email-summarizer` |
|
|
350
|
+
| `AGENT_CODE_PATH` | Path to synthesized DSL code | `/config/agent.rb` |
|
|
351
|
+
| `CONFIG_PATH` | Optional YAML config file | `/config/config.yaml` |
|
|
352
|
+
| `MODEL_ENDPOINTS` | Comma-separated LLM API endpoints | `https://api.anthropic.com/v1/messages` |
|
|
353
|
+
| `MCP_SERVERS` | Comma-separated MCP tool server URLs | `http://gmail.svc:3000,http://slack.svc:3000` |
|
|
354
|
+
| `WORKSPACE_PATH` | Path to persistent workspace | `/workspace` |
|
|
355
|
+
| `AGENT_MODE` | Execution mode (`autonomous` or `scheduled`) | `scheduled` |
|
|
356
|
+
|
|
357
|
+
## Complete Flow Example
|
|
358
|
+
|
|
359
|
+
### 1. User creates agent
|
|
360
|
+
```bash
|
|
361
|
+
$ aictl agent create "check my inbox every hour and send me a summary"
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 2. Operator synthesizes code
|
|
365
|
+
|
|
366
|
+
The operator calls an LLM with a synthesis prompt and receives:
|
|
367
|
+
|
|
368
|
+
```ruby
|
|
369
|
+
agent "inbox-checker-abc123" do
|
|
370
|
+
description "Check inbox hourly and send summary"
|
|
371
|
+
|
|
372
|
+
objectives [
|
|
373
|
+
"Fetch unread emails",
|
|
374
|
+
"Create summary",
|
|
375
|
+
"Send notification"
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
workflow do
|
|
379
|
+
step :fetch, tool: "gmail"
|
|
380
|
+
step :summarize
|
|
381
|
+
step :notify, tool: "gmail"
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 3. Operator creates ConfigMap
|
|
387
|
+
|
|
388
|
+
```yaml
|
|
389
|
+
apiVersion: v1
|
|
390
|
+
kind: ConfigMap
|
|
391
|
+
metadata:
|
|
392
|
+
name: inbox-checker-abc123-code
|
|
393
|
+
data:
|
|
394
|
+
agent.rb: |
|
|
395
|
+
agent "inbox-checker-abc123" do
|
|
396
|
+
description "Check inbox hourly and send summary"
|
|
397
|
+
# ... (full code)
|
|
398
|
+
end
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### 4. Operator creates Pod
|
|
402
|
+
|
|
403
|
+
Pod spec includes:
|
|
404
|
+
- ConfigMap mounted at `/config/agent.rb`
|
|
405
|
+
- Environment variables set
|
|
406
|
+
- Workspace PVC mounted at `/workspace`
|
|
407
|
+
|
|
408
|
+
### 5. Container starts
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
$ /usr/local/bin/agent-runtime
|
|
412
|
+
→ Loads lib/language_operator/agent.rb
|
|
413
|
+
→ Calls LanguageOperator::Agent.run
|
|
414
|
+
→ Creates Agent::Base instance
|
|
415
|
+
→ Loads environment config
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### 6. Agent initializes
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
→ Reads MODEL_ENDPOINTS
|
|
422
|
+
→ Reads MCP_SERVERS
|
|
423
|
+
→ Connects to workspace at /workspace
|
|
424
|
+
→ Checks AGENT_MODE = "scheduled"
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 7. Code loads (future)
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
→ Reads /config/agent.rb
|
|
431
|
+
→ Evaluates DSL code
|
|
432
|
+
→ Registers agent in AgentRegistry
|
|
433
|
+
→ Retrieves agent definition
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### 8. Execution begins
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
→ Executor.execute_workflow(agent_def)
|
|
440
|
+
→ Runs each workflow step
|
|
441
|
+
→ Calls tools via MCP
|
|
442
|
+
→ Calls LLM for reasoning
|
|
443
|
+
→ Writes state to workspace
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## State and Memory
|
|
447
|
+
|
|
448
|
+
Agents maintain state in their workspace:
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
/workspace/
|
|
452
|
+
├── state.json # Current agent state
|
|
453
|
+
├── history.log # Execution history
|
|
454
|
+
├── cache/ # Cached data
|
|
455
|
+
│ └── emails.json
|
|
456
|
+
└── reports/ # Generated outputs
|
|
457
|
+
└── summary.md
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Example state file:**
|
|
461
|
+
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"last_run": "2025-11-08T09:00:00Z",
|
|
465
|
+
"emails_processed": 47,
|
|
466
|
+
"status": "success"
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Agents can read their own state:**
|
|
471
|
+
|
|
472
|
+
```ruby
|
|
473
|
+
workflow do
|
|
474
|
+
step :load_state,
|
|
475
|
+
instruction: "Read /workspace/state.json to see when we last ran"
|
|
476
|
+
|
|
477
|
+
step :fetch_emails,
|
|
478
|
+
tool: "gmail",
|
|
479
|
+
instruction: "Fetch emails since last run timestamp"
|
|
480
|
+
|
|
481
|
+
step :save_state,
|
|
482
|
+
instruction: "Update /workspace/state.json with current timestamp"
|
|
483
|
+
end
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## Tool Integration
|
|
487
|
+
|
|
488
|
+
Agents communicate with MCP tool servers over HTTP:
|
|
489
|
+
|
|
490
|
+
```
|
|
491
|
+
Agent Pod Tool Pod
|
|
492
|
+
┌─────────────┐ ┌──────────┐
|
|
493
|
+
│ │ HTTP POST │ │
|
|
494
|
+
│ Executor │─────────────────▶│ Gmail │
|
|
495
|
+
│ │ /tools/send │ MCP │
|
|
496
|
+
│ │ │ Server │
|
|
497
|
+
│ │◀─────────────────│ │
|
|
498
|
+
│ │ Response │ │
|
|
499
|
+
└─────────────┘ └──────────┘
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
**Tool call example:**
|
|
503
|
+
|
|
504
|
+
```ruby
|
|
505
|
+
# In executor
|
|
506
|
+
def call_tool(tool_name, instruction)
|
|
507
|
+
endpoint = find_tool_endpoint(tool_name)
|
|
508
|
+
|
|
509
|
+
response = HTTP.post("#{endpoint}/tools/execute", json: {
|
|
510
|
+
tool: tool_name,
|
|
511
|
+
instruction: instruction,
|
|
512
|
+
context: current_context
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
response.parse
|
|
516
|
+
end
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## Model Integration
|
|
520
|
+
|
|
521
|
+
Agents call LLM APIs for reasoning:
|
|
522
|
+
|
|
523
|
+
```ruby
|
|
524
|
+
def call_llm(instruction)
|
|
525
|
+
endpoint = @config.model_endpoints.first
|
|
526
|
+
|
|
527
|
+
response = HTTP.post(endpoint, json: {
|
|
528
|
+
model: "claude-3-5-sonnet-20241022",
|
|
529
|
+
messages: [{
|
|
530
|
+
role: "user",
|
|
531
|
+
content: instruction
|
|
532
|
+
}]
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
response.parse["content"]
|
|
536
|
+
end
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## Debugging
|
|
540
|
+
|
|
541
|
+
To inspect a running agent:
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# View agent logs
|
|
545
|
+
$ kubectl logs inbox-checker-abc123
|
|
546
|
+
|
|
547
|
+
# View workspace files
|
|
548
|
+
$ kubectl exec inbox-checker-abc123 -- ls -la /workspace
|
|
549
|
+
|
|
550
|
+
# View synthesized code
|
|
551
|
+
$ kubectl get configmap inbox-checker-abc123-code -o yaml
|
|
552
|
+
|
|
553
|
+
# View environment variables
|
|
554
|
+
$ kubectl exec inbox-checker-abc123 -- env | grep AGENT
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Current Limitations
|
|
558
|
+
|
|
559
|
+
1. **DSL integration not complete:** The synthesized code is stored in ConfigMap but not yet loaded by the runtime
|
|
560
|
+
2. **No workflow execution:** Agents run in generic autonomous mode, not executing defined workflows
|
|
561
|
+
3. **Limited error recovery:** Failed agents don't automatically restart
|
|
562
|
+
4. **No agent-to-agent communication:** Agents can't coordinate with each other yet
|
|
563
|
+
|
|
564
|
+
## Future Enhancements
|
|
565
|
+
|
|
566
|
+
1. **Complete DSL integration:** Wire up ConfigMap code loading into agent runtime
|
|
567
|
+
2. **Workflow engine:** Full support for multi-step workflows with conditionals
|
|
568
|
+
3. **Agent coordination:** Pub/sub system for agent communication
|
|
569
|
+
4. **Hot reloading:** Update agent code without pod restart
|
|
570
|
+
5. **Debugging tools:** Interactive agent inspection and step-through
|
|
571
|
+
|
|
572
|
+
## Related Files
|
|
573
|
+
|
|
574
|
+
- [lib/language_operator/agent.rb](../../lib/language_operator/agent.rb) - Entrypoint
|
|
575
|
+
- [lib/language_operator/agent/base.rb](../../lib/language_operator/agent/base.rb) - Agent initialization
|
|
576
|
+
- [lib/language_operator/agent/executor.rb](../../lib/language_operator/agent/executor.rb) - Execution engine
|
|
577
|
+
- [lib/language_operator/dsl.rb](../../lib/language_operator/dsl.rb) - DSL loader
|
|
578
|
+
- [lib/language_operator/dsl/agent_context.rb](../../lib/language_operator/dsl/agent_context.rb) - Agent registry
|
|
579
|
+
- [lib/language_operator/client/config.rb](../../lib/language_operator/client/config.rb) - Configuration
|
|
580
|
+
- [examples/agent_example.rb](../../examples/agent_example.rb) - DSL example
|
|
581
|
+
|
|
582
|
+
## References
|
|
583
|
+
|
|
584
|
+
- [Language Operator README](../../README.md)
|
|
585
|
+
- [Architecture Review: requirements/reviews/001.md](../../requirements/reviews/001.md)
|