flow-forge-ai-sdk 0.1.0__tar.gz

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 (65) hide show
  1. flow_forge_ai_sdk-0.1.0/PKG-INFO +307 -0
  2. flow_forge_ai_sdk-0.1.0/README.md +255 -0
  3. flow_forge_ai_sdk-0.1.0/pyproject.toml +113 -0
  4. flow_forge_ai_sdk-0.1.0/setup.cfg +4 -0
  5. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/__init__.py +0 -0
  6. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/config/__init__.py +0 -0
  7. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/config/config_handler.py +97 -0
  8. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/config/models.py +66 -0
  9. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/context.py +121 -0
  10. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/emitter.py +33 -0
  11. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/__init__.py +24 -0
  12. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/base.py +84 -0
  13. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/httpx_instr.py +140 -0
  14. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/models/__init__.py +0 -0
  15. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/models/llm_payloads.py +76 -0
  16. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/models/tool_payloads.py +85 -0
  17. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/ollama_instr.py +258 -0
  18. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/openai_instr.py +271 -0
  19. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/requests_instr.py +139 -0
  20. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/trace_tool.py +82 -0
  21. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/utils.py +26 -0
  22. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/instrumentation/workflow.py +39 -0
  23. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/internal_logging/__init__.py +0 -0
  24. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/internal_logging/logger.py +279 -0
  25. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/internal_logging/logging_handler.py +60 -0
  26. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/py.typed +0 -0
  27. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/replay.py +166 -0
  28. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/runtime.py +424 -0
  29. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/__init__.py +24 -0
  30. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/base.py +13 -0
  31. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/composite_sink.py +34 -0
  32. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/console_sink.py +33 -0
  33. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/database_sink.py +166 -0
  34. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/file_sink.py +29 -0
  35. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/__init__.py +24 -0
  36. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/jsonl_handler.py +113 -0
  37. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/mongodb_handler.py +248 -0
  38. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/mysql_handler.py +274 -0
  39. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/postgres_handler.py +284 -0
  40. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/resource_handler.py +154 -0
  41. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/handlers/sqlite_handler.py +247 -0
  42. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/log_sink.py +17 -0
  43. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/memory_sink.py +26 -0
  44. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/models/__init__.py +0 -0
  45. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/models/event.py +63 -0
  46. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/models/run.py +31 -0
  47. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/models/step.py +31 -0
  48. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/sinks/sink_router.py +34 -0
  49. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/utils/__init__.py +0 -0
  50. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/utils/decorators.py +12 -0
  51. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai/utils/toml.py +9 -0
  52. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai_sdk.egg-info/PKG-INFO +307 -0
  53. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai_sdk.egg-info/SOURCES.txt +63 -0
  54. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai_sdk.egg-info/dependency_links.txt +1 -0
  55. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai_sdk.egg-info/requires.txt +40 -0
  56. flow_forge_ai_sdk-0.1.0/src/flow_forge_ai_sdk.egg-info/top_level.txt +1 -0
  57. flow_forge_ai_sdk-0.1.0/tests/test_config.py +101 -0
  58. flow_forge_ai_sdk-0.1.0/tests/test_context.py +298 -0
  59. flow_forge_ai_sdk-0.1.0/tests/test_database_sink.py +83 -0
  60. flow_forge_ai_sdk-0.1.0/tests/test_error_run.py +17 -0
  61. flow_forge_ai_sdk-0.1.0/tests/test_events.py +15 -0
  62. flow_forge_ai_sdk-0.1.0/tests/test_logging.py +291 -0
  63. flow_forge_ai_sdk-0.1.0/tests/test_ollama_instrumentation.py +112 -0
  64. flow_forge_ai_sdk-0.1.0/tests/test_sinks.py +323 -0
  65. flow_forge_ai_sdk-0.1.0/tests/test_span.py +17 -0
@@ -0,0 +1,307 @@
1
+ Metadata-Version: 2.4
2
+ Name: flow-forge-ai-sdk
3
+ Version: 0.1.0
4
+ Summary: Build, trace, inspect, and replay AI workflows with pluggable instrumentation and storage backends.
5
+ Author-email: Alon Yampolski <yampolski.a@gmail.com>
6
+ Maintainer-email: Alon Yampolski <yampolski.a@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/alonzo86/flow-forge-ai
9
+ Project-URL: Documentation, https://github.com/alonzo86/flow-forge-ai#readme
10
+ Project-URL: Repository, https://github.com/alonzo86/flow-forge-ai
11
+ Project-URL: Issues, https://github.com/alonzo86/flow-forge-ai/issues
12
+ Keywords: ai,llm,agents,observability,instrumentation,tracing,workflow,replay,langchain,openai
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ Provides-Extra: httpx-instr
23
+ Requires-Dist: httpx>=0.24.0; extra == "httpx-instr"
24
+ Provides-Extra: openai-instr
25
+ Requires-Dist: openai>=1.0.0; extra == "openai-instr"
26
+ Provides-Extra: ollama-instr
27
+ Requires-Dist: ollama>=0.6.2; extra == "ollama-instr"
28
+ Provides-Extra: langchain-instr
29
+ Requires-Dist: langchain>=1.3.9; extra == "langchain-instr"
30
+ Provides-Extra: postgres-sink
31
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgres-sink"
32
+ Provides-Extra: mongodb-sink
33
+ Requires-Dist: pymongo>=3.12.0; extra == "mongodb-sink"
34
+ Provides-Extra: mysql-sink
35
+ Requires-Dist: mysql-connector-python>=8.0.0; extra == "mysql-sink"
36
+ Provides-Extra: sqlite-sink
37
+ Requires-Dist: pysqlite3>=0.6.0; extra == "sqlite-sink"
38
+ Provides-Extra: ui
39
+ Requires-Dist: flow-forge-ai-sdk-ui>=0.1.0; extra == "ui"
40
+ Provides-Extra: dev
41
+ Requires-Dist: respx>=0.23.1; extra == "dev"
42
+ Requires-Dist: responses>=0.26.1; extra == "dev"
43
+ Requires-Dist: mypy>=2.1.0; extra == "dev"
44
+ Requires-Dist: pytest>=9.0.3; extra == "dev"
45
+ Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
46
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
47
+ Requires-Dist: testcontainers>=4.14.2; extra == "dev"
48
+ Requires-Dist: pylint[spelling]>=4.0.6; extra == "dev"
49
+ Requires-Dist: pip-audit>=2.10.1; extra == "dev"
50
+ Requires-Dist: bandit>=1.9.4; extra == "dev"
51
+ Requires-Dist: build; extra == "dev"
52
+
53
+ # flow-forge-ai
54
+
55
+ Core runtime, instrumentation, and storage package for Flow Forge AI.
56
+
57
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](#installation)
58
+ [![Tests: pytest](https://img.shields.io/badge/tests-pytest-0A9EDC?logo=pytest&logoColor=white)](#development)
59
+ [![Coverage: pytest-cov](https://img.shields.io/badge/coverage-pytest--cov-00A98F)](#development)
60
+ [![Type Checking: pyright](https://img.shields.io/badge/type%20checking-pyright-2C5BB4)](#development)
61
+
62
+ ## What It Does
63
+
64
+ - Wraps workflow code with a lightweight run context (context manager or decorator)
65
+ - Auto-instruments LLM and HTTP libraries so every call emits structured trace events
66
+ - Routes events to one or more configurable sinks (file, console, memory, database)
67
+ - Starts an in-process HTTP listener so the UI can query and replay past runs
68
+
69
+ ## Installation
70
+
71
+ ```bash
72
+ cd core
73
+ pip install -e .
74
+ ```
75
+
76
+ ### Optional Extras
77
+
78
+ Install only the extras you need:
79
+
80
+ ```bash
81
+ # Instrumentors
82
+ pip install -e ".[openai-instr]" # OpenAI
83
+ pip install -e ".[ollama-instr]" # Ollama
84
+ pip install -e ".[httpx-instr]" # httpx
85
+ pip install -e ".[langchain-instr]" # LangChain
86
+
87
+ # Storage backends
88
+ pip install -e ".[sqlite-sink]"
89
+ pip install -e ".[postgres-sink]"
90
+ pip install -e ".[mysql-sink]"
91
+ pip install -e ".[mongodb-sink]"
92
+
93
+ # Development tooling
94
+ pip install -e ".[dev]"
95
+ ```
96
+
97
+ ## Quick Start
98
+
99
+ ### 1. Create a config file
100
+
101
+ ```bash
102
+ cp ../../config.example.toml config.toml
103
+ ```
104
+
105
+ Configuration is loaded automatically from `config.toml` in the current working directory.
106
+
107
+ ### 2. Choose a usage pattern
108
+
109
+ #### Context manager
110
+
111
+ ```python
112
+ from flow_forge_ai.runtime import runtime
113
+
114
+ with runtime.run(workflow="my-workflow") as run_id:
115
+ # instrumented calls inside this block are traced
116
+ print(f"run_id={run_id}")
117
+ ```
118
+
119
+ #### Workflow decorator
120
+
121
+ ```python
122
+ from flow_forge_ai.instrumentation.workflow import workflow
123
+
124
+ @workflow(workflow_id="my-pipeline")
125
+ def pipeline():
126
+ return "done"
127
+
128
+ pipeline()
129
+ ```
130
+
131
+ #### Step decorator
132
+
133
+ ```python
134
+ @workflow(workflow_id="article-summarizer")
135
+ def summarize(articles: list[str]) -> str:
136
+ return combine([summarize_one(a) for a in articles])
137
+
138
+ @summarize.step(step_id="summarize")
139
+ def summarize_one(text: str) -> str:
140
+ ...
141
+
142
+ @summarize.step(step_id="combine")
143
+ def combine(summaries: list[str]) -> str:
144
+ ...
145
+ ```
146
+
147
+ #### Tool tracing
148
+
149
+ ```python
150
+ from flow_forge_ai.instrumentation.trace_tool import trace_tool
151
+
152
+ @trace_tool(version="v1", tool_id="knowledge_base_search")
153
+ def search_knowledge_base(query: str) -> str:
154
+ ...
155
+ ```
156
+
157
+ ### 3. Run an example
158
+
159
+ Examples live in [examples/](examples/):
160
+
161
+ | Example | Instrumentation | Sink |
162
+ |---------|----------------|------|
163
+ | [01_openai_context_manager](examples/01_openai_context_manager/example.py) | OpenAI | JSONL file |
164
+ | [02_ollama_workflow_decorator](examples/02_ollama_workflow_decorator/example.py) | Ollama | SQLite |
165
+ | [03_httpx_context_manager](examples/03_httpx_context_manager/example.py) | httpx | JSONL file |
166
+ | [04_requests_workflow_decorator](examples/04_requests_workflow_decorator/example.py) | requests | JSONL file |
167
+
168
+ ```bash
169
+ cd examples/02_ollama_workflow_decorator
170
+ python example.py
171
+ ```
172
+
173
+ ## Configuration
174
+
175
+ Configuration is TOML-based with three top-level sections.
176
+
177
+ ### `[runtime]`
178
+
179
+ ```toml
180
+ [runtime]
181
+ enable = true
182
+ source_sink = "sqlite log" # sink name used by the replay manager
183
+ listener_host = "127.0.0.1"
184
+ listener_port = 7070
185
+ ```
186
+
187
+ ### `[[instrumentors]]`
188
+
189
+ One entry per library to auto-instrument:
190
+
191
+ ```toml
192
+ [[instrumentors]]
193
+ class_path = "flow_forge_ai.instrumentation.openai_instr.OpenAIInstrumentor"
194
+
195
+ [[instrumentors]]
196
+ class_path = "flow_forge_ai.instrumentation.httpx_instr.HttpxInstrumentor"
197
+ ```
198
+
199
+ ### `[[sinks]]`
200
+
201
+ One entry per output destination. Multiple sinks are supported simultaneously:
202
+
203
+ ```toml
204
+ [[sinks]]
205
+ name = "file log"
206
+ class_path = "flow_forge_ai.sinks.file_sink.FileSink"
207
+
208
+ [sinks.options]
209
+ class_path = "flow_forge_ai.sinks.handlers.jsonl_handler.JsonlHandler"
210
+ path = "./traces.jsonl"
211
+
212
+ [[sinks]]
213
+ name = "sqlite log"
214
+ class_path = "flow_forge_ai.sinks.database_sink.DatabaseSink"
215
+
216
+ [sinks.options]
217
+ class_path = "flow_forge_ai.sinks.handlers.sqlite_handler.SQLiteHandler"
218
+ url = "sqlite:///./runs.db"
219
+ ```
220
+
221
+ ### `env:` expansion in sink options
222
+
223
+ Prefix any sink option value with `env:` to read it from an environment variable at load time:
224
+
225
+ ```toml
226
+ [sinks.options]
227
+ user = "env:FLOW_FORGE_DB_USER"
228
+ password = "env:FLOW_FORGE_DB_PASSWORD"
229
+ ```
230
+
231
+ ## Supported Instrumentors
232
+
233
+ | Class path | Library |
234
+ |-----------|---------|
235
+ | `flow_forge_ai.instrumentation.openai_instr.OpenAIInstrumentor` | `openai` |
236
+ | `flow_forge_ai.instrumentation.ollama_instr.OllamaInstrumentor` | `ollama` |
237
+ | `flow_forge_ai.instrumentation.httpx_instr.HttpxInstrumentor` | `httpx` |
238
+ | `flow_forge_ai.instrumentation.requests_instr.RequestsInstrumentor` | `requests` |
239
+
240
+ ## Supported Sinks
241
+
242
+ | Class path | Storage |
243
+ |-----------|---------|
244
+ | `flow_forge_ai.sinks.file_sink.FileSink` | JSONL file |
245
+ | `flow_forge_ai.sinks.console_sink.ConsoleSink` | stdout |
246
+ | `flow_forge_ai.sinks.memory_sink.MemorySink` | in-process list |
247
+ | `flow_forge_ai.sinks.database_sink.DatabaseSink` | pluggable handler (see below) |
248
+
249
+ `DatabaseSink` delegates persistence to a handler specified via `sinks.options.class_path`:
250
+
251
+ | Handler | Backend |
252
+ |---------|---------|
253
+ | `flow_forge_ai.sinks.handlers.jsonl_handler.JsonlHandler` | JSONL file |
254
+ | `flow_forge_ai.sinks.handlers.sqlite_handler.SQLiteHandler` | SQLite |
255
+ | `flow_forge_ai.sinks.handlers.postgres_handler.PostgresHandler` | PostgreSQL |
256
+ | `flow_forge_ai.sinks.handlers.mysql_handler.MySQLHandler` | MySQL |
257
+ | `flow_forge_ai.sinks.handlers.mongodb_handler.MongoDBHandler` | MongoDB |
258
+
259
+ ## Runtime Replay API
260
+
261
+ When `[runtime].enable = true`, the package starts a local HTTP listener that the UI connects to:
262
+
263
+ | Method | Path | Description |
264
+ |--------|------|-------------|
265
+ | `GET` | `/api/runs` | List all recorded runs |
266
+ | `GET` | `/api/steps?run_id=<id>` | List steps for a run |
267
+ | `POST` | `/api/runs/{run_id}/replay` | Start a replay |
268
+ | `GET` | `/api/runs/{run_id}/replay` | Get replay status |
269
+ | `DELETE` | `/api/runs/{run_id}/replay` | Stop a replay |
270
+
271
+ ## Package Layout
272
+
273
+ ```
274
+ core/
275
+ ├── src/flow_forge_ai/
276
+ │ ├── runtime.py # Runtime entry point (run context manager)
277
+ │ ├── emitter.py # Event emitter
278
+ │ ├── context.py # Run context
279
+ │ ├── replay.py # Replay manager
280
+ │ ├── config/ # Config loading and models
281
+ │ ├── instrumentation/ # Instrumentors + @workflow / @trace_tool decorators
282
+ │ ├── sinks/ # Sink implementations and handlers
283
+ │ ├── internal_logging/ # Internal logger
284
+ │ └── utils/ # Shared utilities
285
+ ├── examples/ # Runnable end-to-end scenarios
286
+ └── tests/ # Unit, integration, and e2e tests
287
+ ```
288
+
289
+ ## Development
290
+
291
+ ```bash
292
+ # Install dev dependencies
293
+ pip install -e ".[dev]"
294
+
295
+ # Run tests
296
+ pytest
297
+
298
+ # Run tests with coverage
299
+ pytest --cov=flow_forge_ai --cov-report=term-missing --cov-report=xml
300
+
301
+ # Type checking
302
+ pyright
303
+
304
+ # Lint (requires enchant)
305
+ brew install enchant
306
+ pylint ./src
307
+ ```
@@ -0,0 +1,255 @@
1
+ # flow-forge-ai
2
+
3
+ Core runtime, instrumentation, and storage package for Flow Forge AI.
4
+
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](#installation)
6
+ [![Tests: pytest](https://img.shields.io/badge/tests-pytest-0A9EDC?logo=pytest&logoColor=white)](#development)
7
+ [![Coverage: pytest-cov](https://img.shields.io/badge/coverage-pytest--cov-00A98F)](#development)
8
+ [![Type Checking: pyright](https://img.shields.io/badge/type%20checking-pyright-2C5BB4)](#development)
9
+
10
+ ## What It Does
11
+
12
+ - Wraps workflow code with a lightweight run context (context manager or decorator)
13
+ - Auto-instruments LLM and HTTP libraries so every call emits structured trace events
14
+ - Routes events to one or more configurable sinks (file, console, memory, database)
15
+ - Starts an in-process HTTP listener so the UI can query and replay past runs
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ cd core
21
+ pip install -e .
22
+ ```
23
+
24
+ ### Optional Extras
25
+
26
+ Install only the extras you need:
27
+
28
+ ```bash
29
+ # Instrumentors
30
+ pip install -e ".[openai-instr]" # OpenAI
31
+ pip install -e ".[ollama-instr]" # Ollama
32
+ pip install -e ".[httpx-instr]" # httpx
33
+ pip install -e ".[langchain-instr]" # LangChain
34
+
35
+ # Storage backends
36
+ pip install -e ".[sqlite-sink]"
37
+ pip install -e ".[postgres-sink]"
38
+ pip install -e ".[mysql-sink]"
39
+ pip install -e ".[mongodb-sink]"
40
+
41
+ # Development tooling
42
+ pip install -e ".[dev]"
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ### 1. Create a config file
48
+
49
+ ```bash
50
+ cp ../../config.example.toml config.toml
51
+ ```
52
+
53
+ Configuration is loaded automatically from `config.toml` in the current working directory.
54
+
55
+ ### 2. Choose a usage pattern
56
+
57
+ #### Context manager
58
+
59
+ ```python
60
+ from flow_forge_ai.runtime import runtime
61
+
62
+ with runtime.run(workflow="my-workflow") as run_id:
63
+ # instrumented calls inside this block are traced
64
+ print(f"run_id={run_id}")
65
+ ```
66
+
67
+ #### Workflow decorator
68
+
69
+ ```python
70
+ from flow_forge_ai.instrumentation.workflow import workflow
71
+
72
+ @workflow(workflow_id="my-pipeline")
73
+ def pipeline():
74
+ return "done"
75
+
76
+ pipeline()
77
+ ```
78
+
79
+ #### Step decorator
80
+
81
+ ```python
82
+ @workflow(workflow_id="article-summarizer")
83
+ def summarize(articles: list[str]) -> str:
84
+ return combine([summarize_one(a) for a in articles])
85
+
86
+ @summarize.step(step_id="summarize")
87
+ def summarize_one(text: str) -> str:
88
+ ...
89
+
90
+ @summarize.step(step_id="combine")
91
+ def combine(summaries: list[str]) -> str:
92
+ ...
93
+ ```
94
+
95
+ #### Tool tracing
96
+
97
+ ```python
98
+ from flow_forge_ai.instrumentation.trace_tool import trace_tool
99
+
100
+ @trace_tool(version="v1", tool_id="knowledge_base_search")
101
+ def search_knowledge_base(query: str) -> str:
102
+ ...
103
+ ```
104
+
105
+ ### 3. Run an example
106
+
107
+ Examples live in [examples/](examples/):
108
+
109
+ | Example | Instrumentation | Sink |
110
+ |---------|----------------|------|
111
+ | [01_openai_context_manager](examples/01_openai_context_manager/example.py) | OpenAI | JSONL file |
112
+ | [02_ollama_workflow_decorator](examples/02_ollama_workflow_decorator/example.py) | Ollama | SQLite |
113
+ | [03_httpx_context_manager](examples/03_httpx_context_manager/example.py) | httpx | JSONL file |
114
+ | [04_requests_workflow_decorator](examples/04_requests_workflow_decorator/example.py) | requests | JSONL file |
115
+
116
+ ```bash
117
+ cd examples/02_ollama_workflow_decorator
118
+ python example.py
119
+ ```
120
+
121
+ ## Configuration
122
+
123
+ Configuration is TOML-based with three top-level sections.
124
+
125
+ ### `[runtime]`
126
+
127
+ ```toml
128
+ [runtime]
129
+ enable = true
130
+ source_sink = "sqlite log" # sink name used by the replay manager
131
+ listener_host = "127.0.0.1"
132
+ listener_port = 7070
133
+ ```
134
+
135
+ ### `[[instrumentors]]`
136
+
137
+ One entry per library to auto-instrument:
138
+
139
+ ```toml
140
+ [[instrumentors]]
141
+ class_path = "flow_forge_ai.instrumentation.openai_instr.OpenAIInstrumentor"
142
+
143
+ [[instrumentors]]
144
+ class_path = "flow_forge_ai.instrumentation.httpx_instr.HttpxInstrumentor"
145
+ ```
146
+
147
+ ### `[[sinks]]`
148
+
149
+ One entry per output destination. Multiple sinks are supported simultaneously:
150
+
151
+ ```toml
152
+ [[sinks]]
153
+ name = "file log"
154
+ class_path = "flow_forge_ai.sinks.file_sink.FileSink"
155
+
156
+ [sinks.options]
157
+ class_path = "flow_forge_ai.sinks.handlers.jsonl_handler.JsonlHandler"
158
+ path = "./traces.jsonl"
159
+
160
+ [[sinks]]
161
+ name = "sqlite log"
162
+ class_path = "flow_forge_ai.sinks.database_sink.DatabaseSink"
163
+
164
+ [sinks.options]
165
+ class_path = "flow_forge_ai.sinks.handlers.sqlite_handler.SQLiteHandler"
166
+ url = "sqlite:///./runs.db"
167
+ ```
168
+
169
+ ### `env:` expansion in sink options
170
+
171
+ Prefix any sink option value with `env:` to read it from an environment variable at load time:
172
+
173
+ ```toml
174
+ [sinks.options]
175
+ user = "env:FLOW_FORGE_DB_USER"
176
+ password = "env:FLOW_FORGE_DB_PASSWORD"
177
+ ```
178
+
179
+ ## Supported Instrumentors
180
+
181
+ | Class path | Library |
182
+ |-----------|---------|
183
+ | `flow_forge_ai.instrumentation.openai_instr.OpenAIInstrumentor` | `openai` |
184
+ | `flow_forge_ai.instrumentation.ollama_instr.OllamaInstrumentor` | `ollama` |
185
+ | `flow_forge_ai.instrumentation.httpx_instr.HttpxInstrumentor` | `httpx` |
186
+ | `flow_forge_ai.instrumentation.requests_instr.RequestsInstrumentor` | `requests` |
187
+
188
+ ## Supported Sinks
189
+
190
+ | Class path | Storage |
191
+ |-----------|---------|
192
+ | `flow_forge_ai.sinks.file_sink.FileSink` | JSONL file |
193
+ | `flow_forge_ai.sinks.console_sink.ConsoleSink` | stdout |
194
+ | `flow_forge_ai.sinks.memory_sink.MemorySink` | in-process list |
195
+ | `flow_forge_ai.sinks.database_sink.DatabaseSink` | pluggable handler (see below) |
196
+
197
+ `DatabaseSink` delegates persistence to a handler specified via `sinks.options.class_path`:
198
+
199
+ | Handler | Backend |
200
+ |---------|---------|
201
+ | `flow_forge_ai.sinks.handlers.jsonl_handler.JsonlHandler` | JSONL file |
202
+ | `flow_forge_ai.sinks.handlers.sqlite_handler.SQLiteHandler` | SQLite |
203
+ | `flow_forge_ai.sinks.handlers.postgres_handler.PostgresHandler` | PostgreSQL |
204
+ | `flow_forge_ai.sinks.handlers.mysql_handler.MySQLHandler` | MySQL |
205
+ | `flow_forge_ai.sinks.handlers.mongodb_handler.MongoDBHandler` | MongoDB |
206
+
207
+ ## Runtime Replay API
208
+
209
+ When `[runtime].enable = true`, the package starts a local HTTP listener that the UI connects to:
210
+
211
+ | Method | Path | Description |
212
+ |--------|------|-------------|
213
+ | `GET` | `/api/runs` | List all recorded runs |
214
+ | `GET` | `/api/steps?run_id=<id>` | List steps for a run |
215
+ | `POST` | `/api/runs/{run_id}/replay` | Start a replay |
216
+ | `GET` | `/api/runs/{run_id}/replay` | Get replay status |
217
+ | `DELETE` | `/api/runs/{run_id}/replay` | Stop a replay |
218
+
219
+ ## Package Layout
220
+
221
+ ```
222
+ core/
223
+ ├── src/flow_forge_ai/
224
+ │ ├── runtime.py # Runtime entry point (run context manager)
225
+ │ ├── emitter.py # Event emitter
226
+ │ ├── context.py # Run context
227
+ │ ├── replay.py # Replay manager
228
+ │ ├── config/ # Config loading and models
229
+ │ ├── instrumentation/ # Instrumentors + @workflow / @trace_tool decorators
230
+ │ ├── sinks/ # Sink implementations and handlers
231
+ │ ├── internal_logging/ # Internal logger
232
+ │ └── utils/ # Shared utilities
233
+ ├── examples/ # Runnable end-to-end scenarios
234
+ └── tests/ # Unit, integration, and e2e tests
235
+ ```
236
+
237
+ ## Development
238
+
239
+ ```bash
240
+ # Install dev dependencies
241
+ pip install -e ".[dev]"
242
+
243
+ # Run tests
244
+ pytest
245
+
246
+ # Run tests with coverage
247
+ pytest --cov=flow_forge_ai --cov-report=term-missing --cov-report=xml
248
+
249
+ # Type checking
250
+ pyright
251
+
252
+ # Lint (requires enchant)
253
+ brew install enchant
254
+ pylint ./src
255
+ ```
@@ -0,0 +1,113 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "flow-forge-ai-sdk"
7
+ version = "0.1.0"
8
+ description = "Build, trace, inspect, and replay AI workflows with pluggable instrumentation and storage backends."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ dependencies = []
12
+ license = "MIT"
13
+
14
+ keywords = [
15
+ "ai",
16
+ "llm",
17
+ "agents",
18
+ "observability",
19
+ "instrumentation",
20
+ "tracing",
21
+ "workflow",
22
+ "replay",
23
+ "langchain",
24
+ "openai"
25
+ ]
26
+
27
+ classifiers = [
28
+ "Development Status :: 4 - Beta",
29
+ "Intended Audience :: Developers",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Topic :: Software Development :: Libraries",
34
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
35
+ ]
36
+
37
+ authors = [
38
+ { name = "Alon Yampolski", email = "yampolski.a@gmail.com" }
39
+ ]
40
+
41
+ maintainers = [
42
+ { name = "Alon Yampolski", email = "yampolski.a@gmail.com" }
43
+ ]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/alonzo86/flow-forge-ai"
47
+ Documentation = "https://github.com/alonzo86/flow-forge-ai#readme"
48
+ Repository = "https://github.com/alonzo86/flow-forge-ai"
49
+ Issues = "https://github.com/alonzo86/flow-forge-ai/issues"
50
+
51
+
52
+ [project.optional-dependencies]
53
+ httpx-instr = [
54
+ "httpx>=0.24.0",
55
+ ]
56
+
57
+ openai-instr = [
58
+ "openai>=1.0.0",
59
+ ]
60
+
61
+ ollama-instr = [
62
+ "ollama>=0.6.2",
63
+ ]
64
+
65
+ langchain-instr = [
66
+ "langchain>=1.3.9",
67
+ ]
68
+
69
+ postgres-sink = [
70
+ "psycopg2-binary>=2.9.0",
71
+ ]
72
+
73
+ mongodb-sink = [
74
+ "pymongo>=3.12.0",
75
+ ]
76
+
77
+ mysql-sink = [
78
+ "mysql-connector-python>=8.0.0",
79
+ ]
80
+
81
+ sqlite-sink = [
82
+ "pysqlite3>=0.6.0",
83
+ ]
84
+
85
+ ui = [
86
+ "flow-forge-ai-sdk-ui>=0.1.0",
87
+ ]
88
+
89
+ dev = [
90
+ "respx>=0.23.1",
91
+ "responses>=0.26.1",
92
+ "mypy>=2.1.0",
93
+ "pytest>=9.0.3",
94
+ "pytest-cov>=7.1.0",
95
+ "pytest-asyncio>=0.21.0",
96
+ "testcontainers>=4.14.2",
97
+ "pylint[spelling]>=4.0.6",
98
+ "pip-audit>=2.10.1",
99
+ "bandit>=1.9.4",
100
+ "build",
101
+ ]
102
+
103
+ [tool.setuptools.packages.find]
104
+ where = ["src"]
105
+
106
+ [tool.setuptools.package-data]
107
+ flow_forge_ai = [
108
+ "py.typed"
109
+ ]
110
+
111
+ [tool.pytest.ini_options]
112
+ pythonpath = ["src", "tests"]
113
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes