@memgrafter/flatagents 0.8.0 → 0.8.3

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,123 @@
1
+ export interface ExecutionLock {
2
+ acquire(key: string): Promise<boolean>;
3
+ release(key: string): Promise<void>;
4
+ }
5
+ export interface PersistenceBackend {
6
+ save(key: string, snapshot: MachineSnapshot): Promise<void>;
7
+ load(key: string): Promise<MachineSnapshot | null>;
8
+ delete(key: string): Promise<void>;
9
+ list(prefix: string): Promise<string[]>;
10
+ }
11
+ export interface ResultBackend {
12
+ write(uri: string, data: any): Promise<void>;
13
+ read(uri: string, options?: {
14
+ block?: boolean;
15
+ timeout?: number;
16
+ }): Promise<any>;
17
+ exists(uri: string): Promise<boolean>;
18
+ delete(uri: string): Promise<void>;
19
+ }
20
+ export interface ExecutionType {
21
+ execute<T>(fn: () => Promise<T>): Promise<T>;
22
+ }
23
+ export interface ExecutionConfig {
24
+ type: "default" | "retry" | "parallel" | "mdap_voting";
25
+ backoffs?: number[];
26
+ jitter?: number;
27
+ n_samples?: number;
28
+ k_margin?: number;
29
+ max_candidates?: number;
30
+ }
31
+ export interface MachineHooks {
32
+ onMachineStart?(context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
33
+ onMachineEnd?(context: Record<string, any>, output: any): any | Promise<any>;
34
+ onStateEnter?(state: string, context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
35
+ onStateExit?(state: string, context: Record<string, any>, output: any): any | Promise<any>;
36
+ onTransition?(from: string, to: string, context: Record<string, any>): string | Promise<string>;
37
+ onError?(state: string, error: Error, context: Record<string, any>): string | null | Promise<string | null>;
38
+ onAction?(action: string, context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
39
+ }
40
+ export interface LLMBackend {
41
+ totalCost: number;
42
+ totalApiCalls: number;
43
+ call(messages: Message[], options?: LLMOptions): Promise<string>;
44
+ callRaw(messages: Message[], options?: LLMOptions): Promise<any>;
45
+ }
46
+ export interface Message {
47
+ role: "system" | "user" | "assistant" | "tool";
48
+ content: string;
49
+ tool_call_id?: string;
50
+ tool_calls?: ToolCall[];
51
+ }
52
+ export interface ToolCall {
53
+ id: string;
54
+ type: "function";
55
+ function: {
56
+ name: string;
57
+ arguments: string;
58
+ };
59
+ }
60
+ export interface LLMOptions {
61
+ temperature?: number;
62
+ max_tokens?: number;
63
+ tools?: ToolDefinition[];
64
+ response_format?: {
65
+ type: "json_object";
66
+ } | {
67
+ type: "text";
68
+ };
69
+ }
70
+ export interface ToolDefinition {
71
+ type: "function";
72
+ function: {
73
+ name: string;
74
+ description?: string;
75
+ parameters?: Record<string, any>;
76
+ };
77
+ }
78
+ export interface MachineInvoker {
79
+ invoke(machineName: string, input: Record<string, any>, options?: {
80
+ timeout?: number;
81
+ }): Promise<Record<string, any>>;
82
+ launch(machineName: string, input: Record<string, any>): Promise<string>;
83
+ }
84
+ export interface MachineSnapshot {
85
+ execution_id: string;
86
+ machine_name: string;
87
+ spec_version: string;
88
+ current_state: string;
89
+ context: Record<string, any>;
90
+ step: number;
91
+ created_at: string;
92
+ event?: string;
93
+ output?: Record<string, any>;
94
+ total_api_calls?: number;
95
+ total_cost?: number;
96
+ parent_execution_id?: string;
97
+ pending_launches?: LaunchIntent[];
98
+ }
99
+ export interface LaunchIntent {
100
+ execution_id: string;
101
+ machine: string;
102
+ input: Record<string, any>;
103
+ launched: boolean;
104
+ }
105
+ export interface BackendConfig {
106
+ persistence?: "memory" | "local" | "redis" | "postgres" | "s3";
107
+ locking?: "none" | "local" | "redis" | "consul";
108
+ results?: "memory" | "redis";
109
+ }
110
+ export const SPEC_VERSION = "0.8.3";
111
+ export interface SDKRuntimeWrapper {
112
+ spec: "flatagents-runtime";
113
+ spec_version: typeof SPEC_VERSION;
114
+ execution_lock?: ExecutionLock;
115
+ persistence_backend?: PersistenceBackend;
116
+ result_backend?: ResultBackend;
117
+ execution_config?: ExecutionConfig;
118
+ machine_hooks?: MachineHooks;
119
+ llm_backend?: LLMBackend;
120
+ machine_invoker?: MachineInvoker;
121
+ backend_config?: BackendConfig;
122
+ machine_snapshot?: MachineSnapshot;
123
+ }
@@ -0,0 +1,395 @@
1
+ /**
2
+ * FlatMachine Configuration Schema
3
+ * ================================
4
+ *
5
+ * A machine defines how agents are connected and executed:
6
+ * states, transitions, conditions, and loops.
7
+ *
8
+ * While flatagents defines WHAT each agent is (model + prompts + output schema),
9
+ * flatmachines defines HOW agents are connected and executed.
10
+ *
11
+ * STRUCTURE:
12
+ * ----------
13
+ * spec - Fixed string "flatmachine"
14
+ * spec_version - Semver string
15
+ * data - The machine configuration
16
+ * metadata - Extensibility layer
17
+ *
18
+ * DERIVED SCHEMAS:
19
+ * ----------------
20
+ * This file (/flatmachine.d.ts) is the SOURCE OF TRUTH for all FlatMachine schemas.
21
+ * Other schemas (JSON Schema, etc.) are DERIVED from this file using scripts.
22
+ * See: /scripts/generate-spec-assets.ts
23
+ *
24
+ * DATA FIELDS:
25
+ * ------------
26
+ * name - Machine identifier
27
+ * expression_engine - "simple" (default) or "cel"
28
+ * context - Initial context values (Jinja2 templates)
29
+ * agents - Map of agent name to config file path or inline config
30
+ * machines - Map of machine name to config file path or inline config
31
+ * states - Map of state name to state definition
32
+ * settings - Optional settings (hooks, etc.)
33
+ *
34
+ * STATE FIELDS:
35
+ * -------------
36
+ * type - "initial" or "final" (optional)
37
+ * agent - Agent name to execute (from agents map)
38
+ * machine - Machine name or array for parallel execution (from machines map)
39
+ * execution - Execution type config: {type: "retry", backoffs: [...], jitter: 0.1}
40
+ * on_error - Error handling: "error_state" or {default: "...", ErrorType: "..."}
41
+ * action - Hook action to execute
42
+ * input - Input mapping (Jinja2 templates)
43
+ * output_to_context - Map agent output to context (Jinja2 templates)
44
+ * output - Final output (for final states)
45
+ * transitions - Ordered list of transitions
46
+ *
47
+ * PARALLEL EXECUTION (v0.4.0):
48
+ * ----------------------------
49
+ * machine - Can be string[] for parallel machine invocation
50
+ * foreach - Jinja2 expression yielding array for dynamic parallelism
51
+ * as - Variable name for current item in foreach (default: "item")
52
+ * key - Jinja2 expression for result key (optional, results array if omitted)
53
+ * mode - Completion semantics: "settled" (default) or "any"
54
+ * timeout - Timeout in seconds (0 = never)
55
+ * launch - Machine(s) to start fire-and-forget
56
+ * launch_input - Input for launched machines
57
+ *
58
+ * NOTE: Only `machine` supports parallel invocation (string[]), not `agent`.
59
+ * Machines are self-healing with checkpoint/resume and error handling.
60
+ * Agents are raw LLM calls that can fail without recovery. Wrap agents in
61
+ * machines to get retry logic, checkpointing, and proper failure handling
62
+ * before running them in parallel.
63
+ *
64
+ * RUNTIME MODEL (v0.4.0):
65
+ * -----------------------
66
+ * All machine invocations are launches. Communication via result backend.
67
+ *
68
+ * machine: child → launch + blocking read
69
+ * machine: [a,b,c] → launch all + wait for all
70
+ * launch: child → launch only, no read
71
+ *
72
+ * URI Scheme: flatagents://{execution_id}/[checkpoint|result]
73
+ *
74
+ * Parent generates child's execution_id, passes it to child. Child writes
75
+ * result to its URI. Parent reads from known URI. No direct messaging.
76
+ *
77
+ * Local SDKs may optimize blocking reads as function returns (in-memory backend).
78
+ * This decouples output from read, enabling both local and distributed execution.
79
+ *
80
+ * Launch intents are checkpointed before execution (outbox pattern).
81
+ * On resume, SDK checks if launched machine exists before re-launching.
82
+ *
83
+ * TRANSITION FIELDS:
84
+ * ------------------
85
+ * condition - Expression to evaluate (optional, default: always true)
86
+ * to - Target state name
87
+ *
88
+ * EXPRESSION SYNTAX (Simple Mode):
89
+ * --------------------------------
90
+ * Comparisons: ==, !=, <, <=, >, >=
91
+ * Boolean: and, or, not
92
+ * Field access: context.field, input.field, output.field
93
+ * Literals: "string", 42, true, false, null
94
+ *
95
+ * Example: "context.score >= 8 and context.round < 4"
96
+ *
97
+ * EXPRESSION SYNTAX (CEL Mode):
98
+ * -----------------------------
99
+ * All simple syntax, plus:
100
+ * List macros: context.items.all(i, i > 0)
101
+ * String methods: context.name.startsWith("test")
102
+ * Timestamps: context.created > now - duration("24h")
103
+ *
104
+ * EXAMPLE CONFIGURATION:
105
+ * ----------------------
106
+ *
107
+ * spec: flatmachine
108
+ * spec_version: "0.7.0"
109
+ *
110
+ * data:
111
+ * name: writer-critic-loop
112
+ *
113
+ * context:
114
+ * product: "{{ input.product }}"
115
+ * score: 0
116
+ * round: 0
117
+ *
118
+ * agents:
119
+ * writer: ./writer.yml
120
+ * critic: ./critic.yml
121
+ *
122
+ * states:
123
+ * start:
124
+ * type: initial
125
+ * transitions:
126
+ * - to: write
127
+ *
128
+ * write:
129
+ * agent: writer
130
+ * execution:
131
+ * type: retry
132
+ * backoffs: [2, 8, 16, 35]
133
+ * jitter: 0.1
134
+ * on_error: error_state
135
+ * input:
136
+ * product: "{{ context.product }}"
137
+ * output_to_context:
138
+ * tagline: "{{ output.tagline }}"
139
+ * transitions:
140
+ * - to: review
141
+ *
142
+ * review:
143
+ * agent: critic
144
+ * input:
145
+ * tagline: "{{ context.tagline }}"
146
+ * output_to_context:
147
+ * score: "{{ output.score }}"
148
+ * round: "{{ context.round + 1 }}"
149
+ * transitions:
150
+ * - condition: "context.score >= 8"
151
+ * to: done
152
+ * - to: write
153
+ *
154
+ * done:
155
+ * type: final
156
+ * output:
157
+ * tagline: "{{ context.tagline }}"
158
+ *
159
+ * metadata:
160
+ * description: "Iterative writer-critic loop"
161
+ *
162
+ * PARALLEL EXECUTION EXAMPLE:
163
+ * ---------------------------
164
+ *
165
+ * states:
166
+ * parallel_review:
167
+ * machine: [legal_review, tech_review, finance_review]
168
+ * input:
169
+ * document: "{{ context.document }}"
170
+ * mode: settled
171
+ * timeout: 120
172
+ * output_to_context:
173
+ * reviews: "{{ output }}"
174
+ * transitions:
175
+ * - to: synthesize
176
+ *
177
+ * DYNAMIC PARALLELISM EXAMPLE:
178
+ * ----------------------------
179
+ *
180
+ * states:
181
+ * process_all:
182
+ * foreach: "{{ context.documents }}"
183
+ * as: doc
184
+ * key: "{{ doc.id }}"
185
+ * machine: doc_processor
186
+ * input:
187
+ * document: "{{ doc }}"
188
+ * mode: settled
189
+ * output_to_context:
190
+ * results: "{{ output }}"
191
+ * transitions:
192
+ * - to: aggregate
193
+ *
194
+ * LAUNCH (FIRE-AND-FORGET) EXAMPLE:
195
+ * ---------------------------------
196
+ *
197
+ * states:
198
+ * kickoff:
199
+ * launch: expensive_analysis
200
+ * launch_input:
201
+ * document: "{{ context.document }}"
202
+ * result_address: "results/{{ context.job_id }}"
203
+ * transitions:
204
+ * - to: continue_immediately
205
+ *
206
+ * PERSISTENCE (v0.2.0):
207
+ * --------------------
208
+ * MachineSnapshot - Wire format for checkpoints (execution_id, state, context, step)
209
+ * PersistenceConfig - Backend config: {enabled: true, backend: "local"|"memory"}
210
+ * checkpoint_on - Events to checkpoint: ["machine_start", "execute", "machine_end"]
211
+ *
212
+ * MACHINE LAUNCHING:
213
+ * ------------------
214
+ * States can launch peer machines via `machine:` field
215
+ * MachineReference - {path: "./peer.yml"} or {inline: {...}}
216
+ *
217
+ * URI SCHEME:
218
+ * -----------
219
+ * Format: flatagents://{execution_id}[/{path}]
220
+ *
221
+ * Paths:
222
+ * /checkpoint - Machine state for resume
223
+ * /result - Final output after completion
224
+ *
225
+ * Examples:
226
+ * flatagents://550e8400-e29b-41d4-a716-446655440000/checkpoint
227
+ * flatagents://550e8400-e29b-41d4-a716-446655440000/result
228
+ *
229
+ * Each machine execution has a unique_id. Parent generates child's ID
230
+ * before launching, enabling parent to know where to read results without
231
+ * any child-to-parent messaging.
232
+ *
233
+ * EXECUTION CONFIG:
234
+ * -----------------
235
+ * type - "default" | "retry" | "parallel" | "mdap_voting"
236
+ * backoffs - Retry: seconds between retries
237
+ * jitter - Retry: random factor (0-1)
238
+ * n_samples - Parallel: number of samples
239
+ * k_margin - MDAP voting: consensus threshold
240
+ * max_candidates - MDAP voting: max candidates
241
+ *
242
+ * MACHINE INPUT:
243
+ * --------------
244
+ * Per-machine input configuration for parallel execution.
245
+ * Use when different machines need different inputs.
246
+ *
247
+ * LAUNCH INTENT:
248
+ * --------------
249
+ * Launch intent for outbox pattern.
250
+ * Recorded in checkpoint before launching to ensure exactly-once semantics.
251
+ *
252
+ * MACHINE SNAPSHOT:
253
+ * -----------------
254
+ * Wire format for checkpoints.
255
+ * parent_execution_id - Lineage tracking (v0.4.0)
256
+ * pending_launches - Outbox pattern (v0.4.0)
257
+ */
258
+
259
+ export const SPEC_VERSION = "0.8.3";
260
+
261
+ export interface MachineWrapper {
262
+ spec: "flatmachine";
263
+ spec_version: string;
264
+ data: MachineData;
265
+ metadata?: Record<string, any>;
266
+ }
267
+
268
+ export interface MachineData {
269
+ name?: string;
270
+ expression_engine?: "simple" | "cel";
271
+ context?: Record<string, any>;
272
+ agents?: Record<string, string | AgentWrapper>;
273
+ machines?: Record<string, string | MachineWrapper>;
274
+ states: Record<string, StateDefinition>;
275
+ settings?: MachineSettings;
276
+ persistence?: PersistenceConfig;
277
+ hooks?: HooksConfig;
278
+ }
279
+
280
+ /**
281
+ * Configuration for loading hooks from file or module.
282
+ *
283
+ * File-based (preferred for self-contained skills):
284
+ * hooks:
285
+ * file: "./hooks.py"
286
+ * class: "MyHooks"
287
+ * args:
288
+ * working_dir: "."
289
+ *
290
+ * Module-based (for installed packages):
291
+ * hooks:
292
+ * module: "mypackage.hooks"
293
+ * class: "MyHooks"
294
+ * args:
295
+ * api_key: "{{ input.api_key }}"
296
+ *
297
+ * Fields:
298
+ * file - Path to Python file containing hooks class (relative to machine.yml)
299
+ * module - Python module path to import
300
+ * class - Class name to instantiate (required)
301
+ * args - Arguments to pass to hooks constructor
302
+ */
303
+ export interface HooksConfig {
304
+ file?: string;
305
+ module?: string;
306
+ class: string;
307
+ args?: Record<string, any>;
308
+ }
309
+
310
+ export interface MachineSettings {
311
+ max_steps?: number;
312
+ parallel_fallback?: "sequential" | "error";
313
+ [key: string]: any;
314
+ }
315
+
316
+ export interface StateDefinition {
317
+ type?: "initial" | "final";
318
+ agent?: string;
319
+ machine?: string | string[] | MachineInput[];
320
+ action?: string;
321
+ execution?: ExecutionConfig;
322
+ on_error?: string | Record<string, string>;
323
+ input?: Record<string, any>;
324
+ output_to_context?: Record<string, any>;
325
+ output?: Record<string, any>;
326
+ transitions?: Transition[];
327
+ tool_loop?: boolean;
328
+ sampling?: "single" | "multi";
329
+ foreach?: string;
330
+ as?: string;
331
+ key?: string;
332
+ mode?: "settled" | "any";
333
+ timeout?: number;
334
+ launch?: string | string[];
335
+ launch_input?: Record<string, any>;
336
+ }
337
+
338
+ export interface MachineInput {
339
+ name: string;
340
+ input?: Record<string, any>;
341
+ }
342
+
343
+ export interface ExecutionConfig {
344
+ type: "default" | "retry" | "parallel" | "mdap_voting";
345
+ backoffs?: number[];
346
+ jitter?: number;
347
+ n_samples?: number;
348
+ k_margin?: number;
349
+ max_candidates?: number;
350
+ }
351
+
352
+ export interface Transition {
353
+ condition?: string;
354
+ to: string;
355
+ }
356
+
357
+ import { AgentWrapper, OutputSchema, ModelConfig } from "./flatagent";
358
+ export { AgentWrapper, OutputSchema };
359
+
360
+ export type FlatmachineConfig = MachineWrapper;
361
+
362
+ export interface LaunchIntent {
363
+ execution_id: string;
364
+ machine: string;
365
+ input: Record<string, any>;
366
+ launched: boolean;
367
+ }
368
+
369
+ export interface MachineSnapshot {
370
+ execution_id: string;
371
+ machine_name: string;
372
+ spec_version: string;
373
+ current_state: string;
374
+ context: Record<string, any>;
375
+ step: number;
376
+ created_at: string;
377
+ event?: string;
378
+ output?: Record<string, any>;
379
+ total_api_calls?: number;
380
+ total_cost?: number;
381
+ parent_execution_id?: string;
382
+ pending_launches?: LaunchIntent[];
383
+ }
384
+
385
+ export interface PersistenceConfig {
386
+ enabled: boolean;
387
+ backend: "local" | "redis" | "memory" | string;
388
+ checkpoint_on?: string[];
389
+ [key: string]: any;
390
+ }
391
+
392
+ export interface MachineReference {
393
+ path?: string;
394
+ inline?: MachineWrapper;
395
+ }