@memgrafter/flatagents 0.8.0 → 0.8.1

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,346 @@
1
+ /**
2
+ * FlatAgents Runtime Interface Spec
3
+ * ==================================
4
+ *
5
+ * This file defines the runtime interfaces that SDKs MUST implement
6
+ * to be considered compliant. These are NOT configuration schemas
7
+ * (see flatagent.d.ts and flatmachine.d.ts for those).
8
+ *
9
+ * REQUIRED IMPLEMENTATIONS:
10
+ * -------------------------
11
+ * - ExecutionLock: NoOpLock (MUST), LocalFileLock (SHOULD)
12
+ * - PersistenceBackend: MemoryBackend (MUST), LocalFileBackend (SHOULD)
13
+ * - ResultBackend: InMemoryResultBackend (MUST)
14
+ * - ExecutionType: Default, Retry, Parallel, MDAPVoting (MUST)
15
+ * - MachineHooks: Base interface (MUST)
16
+ *
17
+ * OPTIONAL IMPLEMENTATIONS:
18
+ * -------------------------
19
+ * - Distributed backends (Redis, Postgres, etc.)
20
+ * - LLMBackend (SDK may use native provider SDKs)
21
+ *
22
+ * EXECUTION LOCKING:
23
+ * ------------------
24
+ * Prevents concurrent execution of the same machine instance.
25
+ *
26
+ * SDKs MUST provide:
27
+ * - NoOpLock: For when locking is handled externally or disabled
28
+ *
29
+ * SDKs SHOULD provide:
30
+ * - LocalFileLock: For single-node deployments using fcntl/flock
31
+ *
32
+ * Distributed deployments should implement Redis/Consul/etcd locks.
33
+ *
34
+ * PERSISTENCE BACKEND:
35
+ * --------------------
36
+ * Storage backend for machine checkpoints.
37
+ *
38
+ * SDKs MUST provide:
39
+ * - MemoryBackend: For testing and ephemeral runs
40
+ *
41
+ * SDKs SHOULD provide:
42
+ * - LocalFileBackend: For durable local storage with atomic writes
43
+ *
44
+ * RESULT BACKEND:
45
+ * ---------------
46
+ * Inter-machine communication via URI-addressed results.
47
+ *
48
+ * URI format: flatagents://{execution_id}/{path}
49
+ * - path is typically "result" or "checkpoint"
50
+ *
51
+ * SDKs MUST provide:
52
+ * - InMemoryResultBackend: For single-process execution
53
+ *
54
+ * EXECUTION TYPES:
55
+ * ----------------
56
+ * Execution strategy for agent calls.
57
+ *
58
+ * SDKs MUST implement all four types:
59
+ * - default: Single call, no retry
60
+ * - retry: Configurable backoffs with jitter
61
+ * - parallel: Run N samples, return all successes
62
+ * - mdap_voting: Multi-sample with consensus voting
63
+ *
64
+ * MACHINE HOOKS:
65
+ * --------------
66
+ * Extension points for machine execution.
67
+ * All methods are optional and can be sync or async.
68
+ *
69
+ * SDKs SHOULD provide:
70
+ * - WebhookHooks: Send events to HTTP endpoint
71
+ * - CompositeHooks: Combine multiple hook implementations
72
+ *
73
+ * LLM BACKEND (OPTIONAL):
74
+ * -----------------------
75
+ * Abstraction over LLM providers.
76
+ *
77
+ * This interface is OPTIONAL - SDKs may use provider SDKs directly.
78
+ * Useful for:
79
+ * - Unified retry/monitoring across providers
80
+ * - Provider-agnostic code
81
+ * - Testing with mock backends
82
+ *
83
+ * MACHINE INVOKER:
84
+ * ----------------
85
+ * Interface for invoking peer machines.
86
+ * Used internally by FlatMachine for `machine:` and `launch:` states.
87
+ *
88
+ * BACKEND CONFIGURATION:
89
+ * ----------------------
90
+ * Backend configuration for machine settings.
91
+ *
92
+ * Example in YAML:
93
+ * settings:
94
+ * backends:
95
+ * persistence: local
96
+ * locking: none
97
+ * results: memory
98
+ */
99
+
100
+ export interface ExecutionLock {
101
+ /**
102
+ * Attempt to acquire exclusive lock for the given key.
103
+ * MUST be non-blocking - returns immediately.
104
+ *
105
+ * @param key - Typically the execution_id
106
+ * @returns true if lock acquired, false if already held by another process
107
+ */
108
+ acquire(key: string): Promise<boolean>;
109
+
110
+ /**
111
+ * Release the lock for the given key.
112
+ * Safe to call even if lock not held.
113
+ */
114
+ release(key: string): Promise<void>;
115
+ }
116
+
117
+ export interface PersistenceBackend {
118
+ /**
119
+ * Save a checkpoint snapshot.
120
+ * MUST be atomic - either fully written or not at all.
121
+ *
122
+ * @param key - Checkpoint identifier (e.g., "{execution_id}/step_{step}")
123
+ * @param snapshot - The machine state to persist
124
+ */
125
+ save(key: string, snapshot: MachineSnapshot): Promise<void>;
126
+
127
+ /**
128
+ * Load a checkpoint snapshot.
129
+ * @returns The snapshot, or null if not found
130
+ */
131
+ load(key: string): Promise<MachineSnapshot | null>;
132
+
133
+ /**
134
+ * Delete a checkpoint.
135
+ * Safe to call if key doesn't exist.
136
+ */
137
+ delete(key: string): Promise<void>;
138
+
139
+ /**
140
+ * List all keys matching a prefix.
141
+ * Used to find all checkpoints for an execution.
142
+ *
143
+ * @param prefix - Key prefix to match (e.g., "{execution_id}/")
144
+ * @returns Array of matching keys, sorted lexicographically
145
+ */
146
+ list(prefix: string): Promise<string[]>;
147
+ }
148
+
149
+ export interface ResultBackend {
150
+ /**
151
+ * Write data to a URI.
152
+ * MUST notify any blocked readers.
153
+ */
154
+ write(uri: string, data: any): Promise<void>;
155
+
156
+ /**
157
+ * Read data from a URI.
158
+ *
159
+ * @param uri - The flatagents:// URI
160
+ * @param options.block - If true, wait until data is available
161
+ * @param options.timeout - Max ms to wait (undefined = forever)
162
+ * @returns The data, or undefined if not found and block=false
163
+ * @throws TimeoutError if timeout expires while blocking
164
+ */
165
+ read(uri: string, options?: {
166
+ block?: boolean;
167
+ timeout?: number;
168
+ }): Promise<any>;
169
+
170
+ /**
171
+ * Check if data exists at a URI without reading it.
172
+ */
173
+ exists(uri: string): Promise<boolean>;
174
+
175
+ /**
176
+ * Delete data at a URI.
177
+ * Safe to call if URI doesn't exist.
178
+ */
179
+ delete(uri: string): Promise<void>;
180
+ }
181
+
182
+ export interface ExecutionType {
183
+ /**
184
+ * Execute a function with this strategy.
185
+ *
186
+ * @param fn - The async function to execute (typically agent.call)
187
+ * @returns The result(s) according to strategy
188
+ */
189
+ execute<T>(fn: () => Promise<T>): Promise<T>;
190
+ }
191
+
192
+ export interface ExecutionConfig {
193
+ type: "default" | "retry" | "parallel" | "mdap_voting";
194
+
195
+ // retry options
196
+ backoffs?: number[]; // seconds between retries
197
+ jitter?: number; // random factor (0-1)
198
+
199
+ // parallel/mdap options
200
+ n_samples?: number; // number of parallel calls
201
+ k_margin?: number; // mdap consensus threshold
202
+ max_candidates?: number;
203
+ }
204
+
205
+ export interface MachineHooks {
206
+ /** Called once at machine start. Can modify initial context. */
207
+ onMachineStart?(context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
208
+
209
+ /** Called once at machine end. Can modify final output. */
210
+ onMachineEnd?(context: Record<string, any>, output: any): any | Promise<any>;
211
+
212
+ /** Called before each state execution. Can modify context. */
213
+ onStateEnter?(state: string, context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
214
+
215
+ /** Called after each state execution. Can modify output. */
216
+ onStateExit?(state: string, context: Record<string, any>, output: any): any | Promise<any>;
217
+
218
+ /** Called before transition. Can redirect to different state. */
219
+ onTransition?(from: string, to: string, context: Record<string, any>): string | Promise<string>;
220
+
221
+ /** Called on error. Return state name to recover, null to propagate. */
222
+ onError?(state: string, error: Error, context: Record<string, any>): string | null | Promise<string | null>;
223
+
224
+ /** Called for custom actions defined in state config. */
225
+ onAction?(action: string, context: Record<string, any>): Record<string, any> | Promise<Record<string, any>>;
226
+ }
227
+
228
+ export interface LLMBackend {
229
+ /** Total cost accumulated across all calls. */
230
+ totalCost: number;
231
+
232
+ /** Total API calls made. */
233
+ totalApiCalls: number;
234
+
235
+ /** Call LLM and return content string. */
236
+ call(messages: Message[], options?: LLMOptions): Promise<string>;
237
+
238
+ /** Call LLM and return raw provider response. */
239
+ callRaw(messages: Message[], options?: LLMOptions): Promise<any>;
240
+ }
241
+
242
+ export interface Message {
243
+ role: "system" | "user" | "assistant" | "tool";
244
+ content: string;
245
+ tool_call_id?: string;
246
+ tool_calls?: ToolCall[];
247
+ }
248
+
249
+ export interface ToolCall {
250
+ id: string;
251
+ type: "function";
252
+ function: {
253
+ name: string;
254
+ arguments: string; // JSON string
255
+ };
256
+ }
257
+
258
+ export interface LLMOptions {
259
+ temperature?: number;
260
+ max_tokens?: number;
261
+ tools?: ToolDefinition[];
262
+ response_format?: { type: "json_object" } | { type: "text" };
263
+ }
264
+
265
+ export interface ToolDefinition {
266
+ type: "function";
267
+ function: {
268
+ name: string;
269
+ description?: string;
270
+ parameters?: Record<string, any>; // JSON Schema
271
+ };
272
+ }
273
+
274
+ export interface MachineInvoker {
275
+ /**
276
+ * Invoke a machine and wait for result.
277
+ */
278
+ invoke(
279
+ machineName: string,
280
+ input: Record<string, any>,
281
+ options?: { timeout?: number }
282
+ ): Promise<Record<string, any>>;
283
+
284
+ /**
285
+ * Launch a machine fire-and-forget style.
286
+ * @returns The execution_id of the launched machine
287
+ */
288
+ launch(
289
+ machineName: string,
290
+ input: Record<string, any>
291
+ ): Promise<string>;
292
+ }
293
+
294
+ export interface MachineSnapshot {
295
+ execution_id: string;
296
+ machine_name: string;
297
+ spec_version: string;
298
+ current_state: string;
299
+ context: Record<string, any>;
300
+ step: number;
301
+ created_at: string;
302
+ event?: string;
303
+ output?: Record<string, any>;
304
+ total_api_calls?: number;
305
+ total_cost?: number;
306
+ parent_execution_id?: string;
307
+ pending_launches?: LaunchIntent[];
308
+ }
309
+
310
+ export interface LaunchIntent {
311
+ execution_id: string;
312
+ machine: string;
313
+ input: Record<string, any>;
314
+ launched: boolean;
315
+ }
316
+
317
+ export interface BackendConfig {
318
+ /** Checkpoint storage. Default: memory */
319
+ persistence?: "memory" | "local" | "redis" | "postgres" | "s3";
320
+
321
+ /** Execution locking. Default: none */
322
+ locking?: "none" | "local" | "redis" | "consul";
323
+
324
+ /** Inter-machine results. Default: memory */
325
+ results?: "memory" | "redis";
326
+ }
327
+
328
+ export const SPEC_VERSION = "0.8.1";
329
+
330
+ /**
331
+ * Wrapper interface for JSON schema generation.
332
+ * Groups all runtime interfaces that SDKs must implement.
333
+ */
334
+ export interface SDKRuntimeWrapper {
335
+ spec: "flatagents-runtime";
336
+ spec_version: typeof SPEC_VERSION;
337
+ execution_lock?: ExecutionLock;
338
+ persistence_backend?: PersistenceBackend;
339
+ result_backend?: ResultBackend;
340
+ execution_config?: ExecutionConfig;
341
+ machine_hooks?: MachineHooks;
342
+ llm_backend?: LLMBackend;
343
+ machine_invoker?: MachineInvoker;
344
+ backend_config?: BackendConfig;
345
+ machine_snapshot?: MachineSnapshot;
346
+ }
@@ -0,0 +1,243 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "#/definitions/SDKRuntimeWrapper",
4
+ "definitions": {
5
+ "SDKRuntimeWrapper": {
6
+ "type": "object",
7
+ "properties": {
8
+ "spec": {
9
+ "type": "string",
10
+ "const": "flatagents-runtime"
11
+ },
12
+ "spec_version": {
13
+ "type": "string",
14
+ "const": "0.8.1"
15
+ },
16
+ "execution_lock": {
17
+ "$ref": "#/definitions/ExecutionLock"
18
+ },
19
+ "persistence_backend": {
20
+ "$ref": "#/definitions/PersistenceBackend"
21
+ },
22
+ "result_backend": {
23
+ "$ref": "#/definitions/ResultBackend"
24
+ },
25
+ "execution_config": {
26
+ "$ref": "#/definitions/ExecutionConfig"
27
+ },
28
+ "machine_hooks": {
29
+ "$ref": "#/definitions/MachineHooks"
30
+ },
31
+ "llm_backend": {
32
+ "$ref": "#/definitions/LLMBackend"
33
+ },
34
+ "machine_invoker": {
35
+ "$ref": "#/definitions/MachineInvoker"
36
+ },
37
+ "backend_config": {
38
+ "$ref": "#/definitions/BackendConfig"
39
+ },
40
+ "machine_snapshot": {
41
+ "$ref": "#/definitions/MachineSnapshot"
42
+ }
43
+ },
44
+ "required": [
45
+ "spec",
46
+ "spec_version"
47
+ ],
48
+ "additionalProperties": false,
49
+ "description": "Wrapper interface for JSON schema generation. Groups all runtime interfaces that SDKs must implement."
50
+ },
51
+ "ExecutionLock": {
52
+ "type": "object",
53
+ "additionalProperties": false,
54
+ "description": "FlatAgents Runtime Interface Spec ==================================\n\nThis file defines the runtime interfaces that SDKs MUST implement to be considered compliant. These are NOT configuration schemas (see flatagent.d.ts and flatmachine.d.ts for those).\n\nREQUIRED IMPLEMENTATIONS:\n------------------------- - ExecutionLock: NoOpLock (MUST), LocalFileLock (SHOULD) - PersistenceBackend: MemoryBackend (MUST), LocalFileBackend (SHOULD) - ResultBackend: InMemoryResultBackend (MUST) - ExecutionType: Default, Retry, Parallel, MDAPVoting (MUST) - MachineHooks: Base interface (MUST)\n\nOPTIONAL IMPLEMENTATIONS:\n------------------------- - Distributed backends (Redis, Postgres, etc.) - LLMBackend (SDK may use native provider SDKs)\n\nEXECUTION LOCKING:\n------------------ Prevents concurrent execution of the same machine instance.\n\nSDKs MUST provide: - NoOpLock: For when locking is handled externally or disabled\n\nSDKs SHOULD provide: - LocalFileLock: For single-node deployments using fcntl/flock\n\nDistributed deployments should implement Redis/Consul/etcd locks.\n\nPERSISTENCE BACKEND:\n-------------------- Storage backend for machine checkpoints.\n\nSDKs MUST provide: - MemoryBackend: For testing and ephemeral runs\n\nSDKs SHOULD provide: - LocalFileBackend: For durable local storage with atomic writes\n\nRESULT BACKEND:\n--------------- Inter-machine communication via URI-addressed results.\n\nURI format: flatagents://{execution_id}/{path} - path is typically \"result\" or \"checkpoint\"\n\nSDKs MUST provide: - InMemoryResultBackend: For single-process execution\n\nEXECUTION TYPES:\n---------------- Execution strategy for agent calls.\n\nSDKs MUST implement all four types: - default: Single call, no retry - retry: Configurable backoffs with jitter - parallel: Run N samples, return all successes - mdap_voting: Multi-sample with consensus voting\n\nMACHINE HOOKS:\n-------------- Extension points for machine execution. All methods are optional and can be sync or async.\n\nSDKs SHOULD provide: - WebhookHooks: Send events to HTTP endpoint - CompositeHooks: Combine multiple hook implementations\n\nLLM BACKEND (OPTIONAL):\n----------------------- Abstraction over LLM providers.\n\nThis interface is OPTIONAL - SDKs may use provider SDKs directly. Useful for: - Unified retry/monitoring across providers - Provider-agnostic code - Testing with mock backends\n\nMACHINE INVOKER:\n---------------- Interface for invoking peer machines. Used internally by FlatMachine for `machine:` and `launch:` states.\n\nBACKEND CONFIGURATION:\n---------------------- Backend configuration for machine settings.\n\nExample in YAML: settings: backends: persistence: local locking: none results: memory"
55
+ },
56
+ "PersistenceBackend": {
57
+ "type": "object",
58
+ "additionalProperties": false
59
+ },
60
+ "ResultBackend": {
61
+ "type": "object",
62
+ "additionalProperties": false
63
+ },
64
+ "ExecutionConfig": {
65
+ "type": "object",
66
+ "properties": {
67
+ "type": {
68
+ "type": "string",
69
+ "enum": [
70
+ "default",
71
+ "retry",
72
+ "parallel",
73
+ "mdap_voting"
74
+ ]
75
+ },
76
+ "backoffs": {
77
+ "type": "array",
78
+ "items": {
79
+ "type": "number"
80
+ }
81
+ },
82
+ "jitter": {
83
+ "type": "number"
84
+ },
85
+ "n_samples": {
86
+ "type": "number"
87
+ },
88
+ "k_margin": {
89
+ "type": "number"
90
+ },
91
+ "max_candidates": {
92
+ "type": "number"
93
+ }
94
+ },
95
+ "required": [
96
+ "type"
97
+ ],
98
+ "additionalProperties": false
99
+ },
100
+ "MachineHooks": {
101
+ "type": "object",
102
+ "additionalProperties": false
103
+ },
104
+ "LLMBackend": {
105
+ "type": "object",
106
+ "properties": {
107
+ "totalCost": {
108
+ "type": "number",
109
+ "description": "Total cost accumulated across all calls."
110
+ },
111
+ "totalApiCalls": {
112
+ "type": "number",
113
+ "description": "Total API calls made."
114
+ }
115
+ },
116
+ "required": [
117
+ "totalCost",
118
+ "totalApiCalls"
119
+ ],
120
+ "additionalProperties": false
121
+ },
122
+ "MachineInvoker": {
123
+ "type": "object",
124
+ "additionalProperties": false
125
+ },
126
+ "BackendConfig": {
127
+ "type": "object",
128
+ "properties": {
129
+ "persistence": {
130
+ "type": "string",
131
+ "enum": [
132
+ "memory",
133
+ "local",
134
+ "redis",
135
+ "postgres",
136
+ "s3"
137
+ ],
138
+ "description": "Checkpoint storage. Default: memory"
139
+ },
140
+ "locking": {
141
+ "type": "string",
142
+ "enum": [
143
+ "none",
144
+ "local",
145
+ "redis",
146
+ "consul"
147
+ ],
148
+ "description": "Execution locking. Default: none"
149
+ },
150
+ "results": {
151
+ "type": "string",
152
+ "enum": [
153
+ "memory",
154
+ "redis"
155
+ ],
156
+ "description": "Inter-machine results. Default: memory"
157
+ }
158
+ },
159
+ "additionalProperties": false
160
+ },
161
+ "MachineSnapshot": {
162
+ "type": "object",
163
+ "properties": {
164
+ "execution_id": {
165
+ "type": "string"
166
+ },
167
+ "machine_name": {
168
+ "type": "string"
169
+ },
170
+ "spec_version": {
171
+ "type": "string"
172
+ },
173
+ "current_state": {
174
+ "type": "string"
175
+ },
176
+ "context": {
177
+ "type": "object"
178
+ },
179
+ "step": {
180
+ "type": "number"
181
+ },
182
+ "created_at": {
183
+ "type": "string"
184
+ },
185
+ "event": {
186
+ "type": "string"
187
+ },
188
+ "output": {
189
+ "type": "object"
190
+ },
191
+ "total_api_calls": {
192
+ "type": "number"
193
+ },
194
+ "total_cost": {
195
+ "type": "number"
196
+ },
197
+ "parent_execution_id": {
198
+ "type": "string"
199
+ },
200
+ "pending_launches": {
201
+ "type": "array",
202
+ "items": {
203
+ "$ref": "#/definitions/LaunchIntent"
204
+ }
205
+ }
206
+ },
207
+ "required": [
208
+ "execution_id",
209
+ "machine_name",
210
+ "spec_version",
211
+ "current_state",
212
+ "context",
213
+ "step",
214
+ "created_at"
215
+ ],
216
+ "additionalProperties": false
217
+ },
218
+ "LaunchIntent": {
219
+ "type": "object",
220
+ "properties": {
221
+ "execution_id": {
222
+ "type": "string"
223
+ },
224
+ "machine": {
225
+ "type": "string"
226
+ },
227
+ "input": {
228
+ "type": "object"
229
+ },
230
+ "launched": {
231
+ "type": "boolean"
232
+ }
233
+ },
234
+ "required": [
235
+ "execution_id",
236
+ "machine",
237
+ "input",
238
+ "launched"
239
+ ],
240
+ "additionalProperties": false
241
+ }
242
+ }
243
+ }