flatagents 0.4.1__py3-none-any.whl

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,141 @@
1
+ """
2
+ Schema validation for flatagent and flatmachine configurations.
3
+
4
+ Uses JSON Schema validation against the bundled schemas.
5
+ Validation errors are warnings by default to avoid breaking user configs.
6
+ """
7
+
8
+ import json
9
+ import warnings
10
+ from importlib.resources import files
11
+ from typing import Any, Dict, List, Optional, Union
12
+
13
+ # Package containing bundled assets
14
+ _ASSETS = files("flatagents.assets")
15
+
16
+
17
+ class ValidationWarning(UserWarning):
18
+ """Warning for schema validation issues."""
19
+ pass
20
+
21
+
22
+ def _load_schema(filename: str) -> Optional[Dict[str, Any]]:
23
+ """Load a JSON schema from bundled assets."""
24
+ try:
25
+ content = (_ASSETS / filename).read_text()
26
+ return json.loads(content)
27
+ except FileNotFoundError:
28
+ return None
29
+
30
+
31
+ def _validate_with_jsonschema(config: Dict[str, Any], schema: Dict[str, Any]) -> List[str]:
32
+ """Validate config against JSON Schema using jsonschema library."""
33
+ try:
34
+ import jsonschema
35
+ except ImportError:
36
+ return [] # Skip validation if jsonschema not installed
37
+
38
+ errors = []
39
+ validator = jsonschema.Draft7Validator(schema)
40
+ for error in validator.iter_errors(config):
41
+ path = ".".join(str(p) for p in error.absolute_path) or "(root)"
42
+ errors.append(f"{path}: {error.message}")
43
+ return errors
44
+
45
+
46
+ def validate_flatagent_config(
47
+ config: Dict[str, Any],
48
+ warn: bool = True,
49
+ strict: bool = False
50
+ ) -> List[str]:
51
+ """
52
+ Validate a flatagent configuration against the schema.
53
+
54
+ Args:
55
+ config: The configuration dictionary to validate
56
+ warn: If True, emit warnings for validation errors (default: True)
57
+ strict: If True, raise ValueError on validation errors (default: False)
58
+
59
+ Returns:
60
+ List of validation error messages (empty if valid)
61
+ """
62
+ schema = _load_schema("flatagent.schema.json")
63
+ if schema is None:
64
+ return [] # Schema not bundled, skip validation
65
+
66
+ errors = _validate_with_jsonschema(config, schema)
67
+
68
+ if errors:
69
+ if strict:
70
+ raise ValueError(
71
+ f"Flatagent config validation failed:\n" +
72
+ "\n".join(f" - {e}" for e in errors)
73
+ )
74
+ elif warn:
75
+ warnings.warn(
76
+ f"Flatagent config has validation issues:\n" +
77
+ "\n".join(f" - {e}" for e in errors),
78
+ ValidationWarning,
79
+ stacklevel=3
80
+ )
81
+
82
+ return errors
83
+
84
+
85
+ def validate_flatmachine_config(
86
+ config: Dict[str, Any],
87
+ warn: bool = True,
88
+ strict: bool = False
89
+ ) -> List[str]:
90
+ """
91
+ Validate a flatmachine configuration against the schema.
92
+
93
+ Args:
94
+ config: The configuration dictionary to validate
95
+ warn: If True, emit warnings for validation errors (default: True)
96
+ strict: If True, raise ValueError on validation errors (default: False)
97
+
98
+ Returns:
99
+ List of validation error messages (empty if valid)
100
+ """
101
+ schema = _load_schema("flatmachine.schema.json")
102
+ if schema is None:
103
+ return [] # Schema not bundled, skip validation
104
+
105
+ errors = _validate_with_jsonschema(config, schema)
106
+
107
+ if errors:
108
+ if strict:
109
+ raise ValueError(
110
+ f"Flatmachine config validation failed:\n" +
111
+ "\n".join(f" - {e}" for e in errors)
112
+ )
113
+ elif warn:
114
+ warnings.warn(
115
+ f"Flatmachine config has validation issues:\n" +
116
+ "\n".join(f" - {e}" for e in errors),
117
+ ValidationWarning,
118
+ stacklevel=3
119
+ )
120
+
121
+ return errors
122
+
123
+
124
+ def get_flatagent_schema() -> Optional[Dict[str, Any]]:
125
+ """Get the bundled flatagent JSON schema."""
126
+ return _load_schema("flatagent.schema.json")
127
+
128
+
129
+ def get_flatmachine_schema() -> Optional[Dict[str, Any]]:
130
+ """Get the bundled flatmachine JSON schema."""
131
+ return _load_schema("flatmachine.schema.json")
132
+
133
+
134
+ def get_asset(filename: str) -> str:
135
+ """Get the contents of a bundled asset file."""
136
+ return (_ASSETS / filename).read_text()
137
+
138
+
139
+ def _get_asset_path(filename: str):
140
+ """Internal: Get a Traversable for a bundled asset file."""
141
+ return _ASSETS / filename
@@ -0,0 +1,310 @@
1
+ Metadata-Version: 2.4
2
+ Name: flatagents
3
+ Version: 0.4.1
4
+ Summary: A lightweight framework for building LLM-powered agents and composable state machines with pluggable backends.
5
+ Project-URL: Homepage, https://github.com/memgrafter/flatagents
6
+ Project-URL: Repository, https://github.com/memgrafter/flatagents
7
+ Project-URL: Issues, https://github.com/memgrafter/flatagents/issues
8
+ Author-email: memgrafter@gmail.com
9
+ License-Expression: Apache-2.0
10
+ Keywords: agents,ai,aisuite,framework,litellm,llm
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: aiofiles
22
+ Requires-Dist: httpx
23
+ Requires-Dist: jinja2
24
+ Requires-Dist: pyyaml
25
+ Provides-Extra: aisuite
26
+ Requires-Dist: aisuite[all]; extra == 'aisuite'
27
+ Provides-Extra: all
28
+ Requires-Dist: aisuite[all]; extra == 'all'
29
+ Requires-Dist: cel-python; extra == 'all'
30
+ Requires-Dist: jsonschema>=4.0; extra == 'all'
31
+ Requires-Dist: litellm; extra == 'all'
32
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'all'
33
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0; extra == 'all'
34
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'all'
35
+ Provides-Extra: cel
36
+ Requires-Dist: cel-python; extra == 'cel'
37
+ Provides-Extra: gcp
38
+ Requires-Dist: aisuite[all]; extra == 'gcp'
39
+ Requires-Dist: cel-python; extra == 'gcp'
40
+ Requires-Dist: google-cloud-firestore>=2.11.0; extra == 'gcp'
41
+ Requires-Dist: jsonschema>=4.0; extra == 'gcp'
42
+ Requires-Dist: litellm; extra == 'gcp'
43
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'gcp'
44
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0; extra == 'gcp'
45
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'gcp'
46
+ Provides-Extra: litellm
47
+ Requires-Dist: litellm; extra == 'litellm'
48
+ Provides-Extra: local
49
+ Requires-Dist: aisuite[all]; extra == 'local'
50
+ Requires-Dist: cel-python; extra == 'local'
51
+ Requires-Dist: jsonschema>=4.0; extra == 'local'
52
+ Requires-Dist: litellm; extra == 'local'
53
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'local'
54
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0; extra == 'local'
55
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'local'
56
+ Provides-Extra: metrics
57
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'metrics'
58
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0; extra == 'metrics'
59
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'metrics'
60
+ Provides-Extra: validation
61
+ Requires-Dist: jsonschema>=4.0; extra == 'validation'
62
+ Description-Content-Type: text/markdown
63
+
64
+ # FlatAgents
65
+
66
+ Define LLM agents in YAML. Run them anywhere.
67
+
68
+ **For LLM/machine readers:** see [MACHINES.md](./MACHINES.md) for comprehensive reference.
69
+
70
+ ## Why?
71
+
72
+ - **Composition over inheritance** — compose stateless agents and checkpointable machines
73
+ - **Compact structure** — easy for LLMs to read and generate
74
+ - **Simple hook interfaces** — escape hatches without complexity; webhook ready
75
+ - **Inspectable** — every agent and machine is readable config
76
+ - **Language-agnostic** — reduce code in any particular runtime
77
+ - **Common TypeScript interface** — single schema for agents, single schema for machines
78
+ - **Limitations** — machine topologies can get complex at scale
79
+
80
+ *Inspired by Kubernetes manifests and character card specifications.*
81
+
82
+ ## Core Concepts
83
+
84
+ Use machines to write flatagents and flatmachines, they are designed for LLMs.
85
+
86
+ | Term | What it is |
87
+ |------|------------|
88
+ | **FlatAgent** | A single LLM call: model + prompts + output schema |
89
+ | **FlatMachine** | A state machine that orchestrates multiple agents, actions, and state machines |
90
+
91
+ Use FlatAgent alone for simple tasks. Use FlatMachine when you need multi-step workflows, branching, or error handling.
92
+
93
+ ## Examples
94
+
95
+ | Example | What it demonstrates |
96
+ |---------|---------------------|
97
+ | [helloworld](./sdk/python/examples/helloworld) | Minimal setup — single agent, single state machine |
98
+ | [writer_critic](./sdk/python/examples/writer_critic) | Multi-agent loop — writer drafts, critic reviews, iterates |
99
+ | [story_writer](./sdk/python/examples/story_writer) | Multi-step creative workflow with chapter generation |
100
+ | [human_in_loop](./sdk/python/examples/human_in_loop) | Pause execution for human approval via hooks |
101
+ | [error_handling](./sdk/python/examples/error_handling) | Error recovery and retry patterns at state machine level |
102
+ | [dynamic_agent](./sdk/python/examples/dynamic_agent) | On-the-fly agent generation from runtime context |
103
+ | [character_card](./sdk/python/examples/character_card) | Loading agent config from character card format |
104
+ | [mdap](./sdk/python/examples/mdap) | MDAP voting execution — multi-sample consensus |
105
+ | [gepa_self_optimizer](./sdk/python/examples/gepa_self_optimizer) | Self-optimizing prompts via reflection and critique |
106
+ | [research_paper_analysis](./sdk/python/examples/research_paper_analysis) | Document analysis with structured extraction |
107
+ | [multi_paper_synthesizer](./sdk/python/examples/multi_paper_synthesizer) | Cross-document synthesis with dynamic machine launching |
108
+ | [support_triage_json](./sdk/python/examples/support_triage_json) | JSON input/output with classification pipeline |
109
+ | [parallelism](./sdk/python/examples/parallelism) | Parallel machines, dynamic foreach, fire-and-forget launches |
110
+
111
+ ## Quick Start
112
+
113
+ ```bash
114
+ pip install flatagents[all]
115
+ ```
116
+
117
+ ```python
118
+ from flatagents import FlatAgent
119
+
120
+ agent = FlatAgent(config_file="reviewer.yml")
121
+ result = await agent.call(query="Review this code...")
122
+ print(result.output)
123
+ ```
124
+
125
+ ## Example Agent
126
+
127
+ **reviewer.yml**
128
+ ```yaml
129
+ spec: flatagent
130
+ spec_version: "0.0.0"
131
+
132
+ data:
133
+ name: code-reviewer
134
+
135
+ model:
136
+ provider: openai
137
+ name: gpt-4
138
+ temperature: 0.3
139
+
140
+ system: |
141
+ You are a senior code reviewer. Analyze code for bugs,
142
+ style issues, and potential improvements.
143
+
144
+ user: |
145
+ Review this code:
146
+ {{ input.code }}
147
+
148
+ output:
149
+ issues:
150
+ type: list
151
+ items:
152
+ type: str
153
+ description: "List of issues found"
154
+ rating:
155
+ type: str
156
+ enum: ["good", "needs_work", "critical"]
157
+ description: "Overall code quality"
158
+ ```
159
+
160
+ **What the fields mean:**
161
+
162
+ - **spec/spec_version** — Format identifier and version
163
+ - **data.name** — Agent identifier
164
+ - **data.model** — LLM provider, model name, and parameters
165
+ - **data.system** — System prompt (sets behavior)
166
+ - **data.user** — User prompt template (uses Jinja2, `{{ input.* }}` for runtime values)
167
+ - **data.output** — Structured output schema (the runtime extracts these fields)
168
+
169
+ ## Output Types
170
+
171
+ ```yaml
172
+ output:
173
+ answer: { type: str }
174
+ count: { type: int }
175
+ score: { type: float }
176
+ valid: { type: bool }
177
+ raw: { type: json }
178
+ items: { type: list, items: { type: str } }
179
+ metadata: { type: object, properties: { key: { type: str } } }
180
+ ```
181
+
182
+ Use `enum: [...]` to constrain string values.
183
+
184
+ ## Multi-Agent Workflows
185
+
186
+ For orchestration, use FlatMachine ([full docs in MACHINES.md](./MACHINES.md)):
187
+
188
+ ```python
189
+ from flatagents import FlatMachine
190
+
191
+ machine = FlatMachine(config_file="workflow.yml")
192
+ result = await machine.execute(input={"query": "..."})
193
+ ```
194
+
195
+ FlatMachine provides: state transitions, conditional branching, loops, retry with backoff, and error recovery—all in YAML.
196
+
197
+ ## Features
198
+
199
+ - Checkpoint and restore
200
+ - Python SDK (TypeScript SDK in progress)
201
+ - [MACHINES.md](./MACHINES.md) — LLM-optimized reference docs
202
+ - Decider agents and machines
203
+ - On-the-fly agent and machine definitions
204
+ - Webhook hooks for remote state machine handling
205
+ - Metrics and logging
206
+ - Error recovery and exception handling at the state machine level
207
+ - Parallel machine execution (`machine: [a, b, c]`)
208
+ - Dynamic parallelism with `foreach`
209
+ - Fire-and-forget launches for background tasks
210
+
211
+ ## Planned
212
+
213
+ - Distributed execution — cross-network machine peering, inter-machine strategies
214
+ - SQL persistence backend
215
+ - TypeScript SDK
216
+ - `max_depth` config to limit machine launch nesting
217
+ - Checkpoint pruning to prevent storage explosion
218
+ - `$root/` path prefix — resolve agent/machine refs from workspace root, not config dir
219
+ - Input size validation — warn when prompt exceeds model context window
220
+ - Serialization warnings — flag non-JSON-serializable context values before checkpoint
221
+
222
+ ## Specs
223
+
224
+ TypeScript definitions are the source of truth:
225
+ - [`flatagent.d.ts`](./flatagent.d.ts)
226
+ - [`flatmachine.d.ts`](./flatmachine.d.ts)
227
+
228
+ ## Python SDK
229
+
230
+ ```bash
231
+ pip install flatagents[litellm]
232
+ ```
233
+
234
+ ### LLM Backends
235
+
236
+ ```python
237
+ from flatagents import LiteLLMBackend, AISuiteBackend
238
+
239
+ # LiteLLM (default)
240
+ agent = FlatAgent(config_file="agent.yml")
241
+
242
+ # AISuite
243
+ backend = AISuiteBackend(model="openai:gpt-4o")
244
+ agent = FlatAgent(config_file="agent.yml", backend=backend)
245
+ ```
246
+
247
+ ### Hooks
248
+
249
+ Extend machine behavior with Python hooks:
250
+
251
+ ```python
252
+ from flatagents import FlatMachine, MachineHooks
253
+
254
+ class CustomHooks(MachineHooks):
255
+ def on_state_enter(self, state: str, context: dict) -> dict:
256
+ context["entered_at"] = time.time()
257
+ return context
258
+
259
+ def on_action(self, action: str, context: dict) -> dict:
260
+ if action == "fetch_data":
261
+ context["data"] = fetch_from_api()
262
+ return context
263
+
264
+ machine = FlatMachine(config_file="machine.yml", hooks=CustomHooks())
265
+ ```
266
+
267
+ **Available hooks**: `on_machine_start`, `on_machine_end`, `on_state_enter`, `on_state_exit`, `on_transition`, `on_error`, `on_action`
268
+
269
+ ### Execution Types
270
+
271
+ ```yaml
272
+ execution:
273
+ type: retry # retry | parallel | mdap_voting
274
+ backoffs: [2, 8, 16, 35] # Seconds between retries
275
+ jitter: 0.1 # ±10% random variation
276
+ ```
277
+
278
+ | Type | Use Case |
279
+ |------|----------|
280
+ | `default` | Single call |
281
+ | `retry` | Rate limit handling with backoff |
282
+ | `parallel` | Multiple samples (`n_samples`) |
283
+ | `mdap_voting` | Consensus voting (`k_margin`, `max_candidates`) |
284
+
285
+ ### Schema Validation
286
+
287
+ ```python
288
+ from flatagents import validate_flatagent_config, validate_flatmachine_config
289
+
290
+ warnings = validate_flatagent_config(config)
291
+ warnings = validate_flatmachine_config(config)
292
+ ```
293
+
294
+ ### Logging & Metrics
295
+
296
+ ```python
297
+ from flatagents import setup_logging, get_logger
298
+
299
+ setup_logging(level="INFO") # Respects FLATAGENTS_LOG_LEVEL env var
300
+ logger = get_logger(__name__)
301
+ ```
302
+
303
+ **Env vars**: `FLATAGENTS_LOG_LEVEL` (`DEBUG`/`INFO`/`WARNING`/`ERROR`), `FLATAGENTS_LOG_FORMAT` (`standard`/`json`/`simple`)
304
+
305
+ For OpenTelemetry metrics:
306
+
307
+ ```bash
308
+ pip install flatagents[metrics]
309
+ export FLATAGENTS_METRICS_ENABLED=true
310
+ ```
@@ -0,0 +1,28 @@
1
+ flatagents/__init__.py,sha256=pOSyQ5XS3iX-HkLRLsqQAUSEYHRg4a7z2X6TASSf-EQ,2957
2
+ flatagents/actions.py,sha256=B5rkNVJ9M4GV0xRYJxpXSjbAe_oJpZyc-Ik5ImFqcHg,7851
3
+ flatagents/backends.py,sha256=RAeeL_m9AzE705oaVxezHG82r9Ix_iNSPvgHMpBSzWI,6061
4
+ flatagents/baseagent.py,sha256=YxVNK_P7S4kOQlOAcb_uoloM1oSEuNvSs6VybsqGqJI,30843
5
+ flatagents/execution.py,sha256=wXjmS9RD9JVbhIzaDSO11B1OnNNtFUbQpokiZsnMcsI,14401
6
+ flatagents/flatagent.py,sha256=-fbx2CezKOahOtgR-nQU40b8bcaNko5-dVyQoVD3IU8,25621
7
+ flatagents/flatmachine.py,sha256=4FQmY54gbtJ8SRSOI93GLsCeEYjvpdBO6ij9NvdgNqc,44288
8
+ flatagents/hooks.py,sha256=Kx96ARxZs-5s7foOpy4IKb2trVx92vzAzVjEsX0hqGQ,12042
9
+ flatagents/locking.py,sha256=QjIknWB2FX0Yr3sAPlkweigPNUgKyUcnKLO-756TZFI,2127
10
+ flatagents/monitoring.py,sha256=GYmibtNFwY0lFi61HdqO9JfKMw4MEcOsyvFBlO2Pycw,13149
11
+ flatagents/persistence.py,sha256=ARHvxidHBTTKr_FB-XLvyE7QLSxXxseodTYNDj-z6M4,7541
12
+ flatagents/utils.py,sha256=iEA-XTN-90IORjWq-v-Xl8_uD70eihbYMmZkx--4IFw,1115
13
+ flatagents/validation.py,sha256=rp19cz6Zlbce_yMqw3YJ5KMSuMjQnoCCJ-DV62zDyU0,4166
14
+ flatagents/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ flatagents/assets/flatagent.d.ts,sha256=XMi4VZUB7yCV4GuYF7dD4RrsWpCg3S6hPoWe3xqJHJA,5818
16
+ flatagents/assets/flatagent.schema.json,sha256=IjkBIMI6uWNcRD98Aqz4ncGpXA9Y3HZC_Qh0-Z2C_TU,4333
17
+ flatagents/assets/flatagent.slim.d.ts,sha256=7QlSeDQYVaVXvo_wCxL_apU6-GnsXXe1KbW3vlsAupU,1321
18
+ flatagents/assets/flatmachine.d.ts,sha256=J1qRTInuko8GZHowQIehKWVkpTKS4GTxOVjej_hNdPs,10910
19
+ flatagents/assets/flatmachine.schema.json,sha256=B2NRmMNUTRDTneaTcXE1gfy97T35n-mFQMGwHuaDg3c,11175
20
+ flatagents/assets/flatmachine.slim.d.ts,sha256=_vTzpLuN3e_3iHQKMK-EfoXw9zxqLeiyfV_j_1wnNgg,2636
21
+ flatagents/expressions/__init__.py,sha256=kk7P97dtcuJ1C0XCvZSkyO8VOBTbwr3Lyi6b8gTIXgo,1683
22
+ flatagents/expressions/cel.py,sha256=yklm062UTG8G2a1-IZfU8A2XtcK48Qmc0AhbJICN1Ac,3127
23
+ flatagents/expressions/simple.py,sha256=zLZHcRXb62qITAomMxOedfCvIthxVSyIH5MtNesFrIc,5774
24
+ flatagents/gcp/__init__.py,sha256=YYtC7H24q624x9r6zdDpsDCTk1O5zzls8WmGiAOqZxc,537
25
+ flatagents/gcp/firestore.py,sha256=qmNMgoBQp6AzUsY5kHAKmfd1qSlhCX0JRSNdHX60g1A,7229
26
+ flatagents-0.4.1.dist-info/METADATA,sha256=AAkacvwHxnubpJTVejG0TMg_7A9xHzs2C5E3Px2fe7w,10732
27
+ flatagents-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
28
+ flatagents-0.4.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any