agentic-lab 0.1.0__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.
Files changed (114) hide show
  1. agentic_lab-0.1.0.dist-info/METADATA +387 -0
  2. agentic_lab-0.1.0.dist-info/RECORD +114 -0
  3. agentic_lab-0.1.0.dist-info/WHEEL +4 -0
  4. agentic_lab-0.1.0.dist-info/entry_points.txt +6 -0
  5. agentlab/__init__.py +269 -0
  6. agentlab/_defaults.toml +40 -0
  7. agentlab/_proto/__init__.py +23 -0
  8. agentlab/_proto/trace_pb2.py +132 -0
  9. agentlab/_proto/trace_pb2.pyi +835 -0
  10. agentlab/bridges/__init__.py +10 -0
  11. agentlab/bridges/otel_genai.py +351 -0
  12. agentlab/cli.py +636 -0
  13. agentlab/config.py +280 -0
  14. agentlab/core/__init__.py +247 -0
  15. agentlab/core/_clock.py +41 -0
  16. agentlab/core/_fmt.py +64 -0
  17. agentlab/core/_replay_seam.py +125 -0
  18. agentlab/core/agent.py +179 -0
  19. agentlab/core/attributes.py +114 -0
  20. agentlab/core/budget.py +31 -0
  21. agentlab/core/context.py +672 -0
  22. agentlab/core/continuation.py +160 -0
  23. agentlab/core/cost.py +95 -0
  24. agentlab/core/determinism.py +1144 -0
  25. agentlab/core/env.py +392 -0
  26. agentlab/core/eval.py +180 -0
  27. agentlab/core/guardrail.py +203 -0
  28. agentlab/core/handles.py +495 -0
  29. agentlab/core/handoff.py +347 -0
  30. agentlab/core/ids.py +141 -0
  31. agentlab/core/link.py +152 -0
  32. agentlab/core/llm.py +530 -0
  33. agentlab/core/memory.py +138 -0
  34. agentlab/core/message.py +205 -0
  35. agentlab/core/op.py +207 -0
  36. agentlab/core/op_names.py +33 -0
  37. agentlab/core/retrieval.py +139 -0
  38. agentlab/core/run.py +277 -0
  39. agentlab/core/span.py +894 -0
  40. agentlab/core/span_event.py +305 -0
  41. agentlab/core/status.py +61 -0
  42. agentlab/core/step.py +689 -0
  43. agentlab/core/tool.py +285 -0
  44. agentlab/core/types.py +22 -0
  45. agentlab/errors.py +760 -0
  46. agentlab/integrations/__init__.py +6 -0
  47. agentlab/integrations/langchain/__init__.py +15 -0
  48. agentlab/integrations/langchain/_callbacks.py +345 -0
  49. agentlab/integrations/langchain/_helpers.py +148 -0
  50. agentlab/io/__init__.py +31 -0
  51. agentlab/io/format.py +293 -0
  52. agentlab/io/http_capture.py +1064 -0
  53. agentlab/io/http_format.py +449 -0
  54. agentlab/io/otel_attributes.py +463 -0
  55. agentlab/io/proto/__init__.py +26 -0
  56. agentlab/io/proto/codec.py +1321 -0
  57. agentlab/io/proto/framing.py +156 -0
  58. agentlab/io/proto/reader.py +188 -0
  59. agentlab/io/proto/writer.py +299 -0
  60. agentlab/io/reader.py +237 -0
  61. agentlab/io/redaction.py +376 -0
  62. agentlab/io/writer.py +408 -0
  63. agentlab/llm/__init__.py +106 -0
  64. agentlab/llm/_autoemit.py +540 -0
  65. agentlab/llm/base.py +355 -0
  66. agentlab/llm/errors.py +60 -0
  67. agentlab/llm/factory.py +79 -0
  68. agentlab/llm/matchers/__init__.py +120 -0
  69. agentlab/llm/matchers/_common.py +435 -0
  70. agentlab/llm/matchers/anthropic.py +517 -0
  71. agentlab/llm/matchers/bedrock.py +511 -0
  72. agentlab/llm/matchers/google.py +543 -0
  73. agentlab/llm/matchers/openai.py +1200 -0
  74. agentlab/llm/pricing.py +267 -0
  75. agentlab/llm/providers/__init__.py +5 -0
  76. agentlab/llm/providers/openrouter.py +442 -0
  77. agentlab/llm/types.py +484 -0
  78. agentlab/promote.py +291 -0
  79. agentlab/py.typed +0 -0
  80. agentlab/pytest.py +280 -0
  81. agentlab/recorder.py +1027 -0
  82. agentlab/replay/__init__.py +93 -0
  83. agentlab/replay/api.py +365 -0
  84. agentlab/replay/cache.py +350 -0
  85. agentlab/replay/context.py +26 -0
  86. agentlab/replay/diff.py +313 -0
  87. agentlab/replay/drift.py +92 -0
  88. agentlab/replay/session.py +294 -0
  89. agentlab/storage/__init__.py +39 -0
  90. agentlab/storage/base.py +381 -0
  91. agentlab/storage/factory.py +104 -0
  92. agentlab/storage/jsonl_store.py +576 -0
  93. agentlab/storage/names.py +602 -0
  94. agentlab/storage/proto_store.py +444 -0
  95. agentlab/ui/README.md +86 -0
  96. agentlab/ui/__init__.py +16 -0
  97. agentlab/ui/_agents.py +412 -0
  98. agentlab/ui/_assets/__init__.py +10 -0
  99. agentlab/ui/_assets/dist/assets/index-DGnShqkT.js +211 -0
  100. agentlab/ui/_assets/dist/assets/index-DqoRSI-a.css +1 -0
  101. agentlab/ui/_assets/dist/favicon.svg +11 -0
  102. agentlab/ui/_assets/dist/index.html +29 -0
  103. agentlab/ui/_dto.py +325 -0
  104. agentlab/ui/_errors.py +51 -0
  105. agentlab/ui/_mapping.py +350 -0
  106. agentlab/ui/_runtime.py +75 -0
  107. agentlab/ui/_server/__init__.py +9 -0
  108. agentlab/ui/_server/agents.py +446 -0
  109. agentlab/ui/_server/agents_overview.py +242 -0
  110. agentlab/ui/_server/app.py +672 -0
  111. agentlab/ui/_server/dashboard.py +316 -0
  112. agentlab/ui/_server/replay_runner.py +466 -0
  113. agentlab/ui/_server/validation.py +80 -0
  114. agentlab/ui/_server/watcher.py +101 -0
@@ -0,0 +1,387 @@
1
+ Metadata-Version: 2.3
2
+ Name: agentic-lab
3
+ Version: 0.1.0
4
+ Summary: Universal record-and-replay for LLM agents.
5
+ Keywords: llm,agents,replay,tracing,evals
6
+ Author: Ambuj Agrawal, Garima Luthra
7
+ Author-email: Ambuj Agrawal <ambujagrawal741@gmail.com>, Garima Luthra <garimaluthra2198@gmail.com>
8
+ License: Apache-2.0
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
13
+ Classifier: Typing :: Typed
14
+ Requires-Dist: httpx>=0.27,<1.0
15
+ Requires-Dist: pydantic>=2.7,<3.0
16
+ Requires-Dist: pydantic-settings>=2.4,<3.0
17
+ Requires-Dist: structlog>=24.1,<26.0
18
+ Requires-Dist: tenacity>=8.5,<10.0
19
+ Requires-Dist: python-dotenv>=1.0,<2.0
20
+ Requires-Dist: protobuf>=5.27,<7.0
21
+ Requires-Dist: pytest>=8.2,<9.0 ; extra == 'dev'
22
+ Requires-Dist: pytest-asyncio>=0.23,<1.0 ; extra == 'dev'
23
+ Requires-Dist: pytest-cov>=5.0,<7.0 ; extra == 'dev'
24
+ Requires-Dist: pytest-xdist[psutil]>=3.6,<4.0 ; extra == 'dev'
25
+ Requires-Dist: respx>=0.21,<1.0 ; extra == 'dev'
26
+ Requires-Dist: ruff>=0.6,<1.0 ; extra == 'dev'
27
+ Requires-Dist: mypy>=1.11,<2.0 ; extra == 'dev'
28
+ Requires-Dist: pre-commit>=3.7,<5.0 ; extra == 'dev'
29
+ Requires-Dist: openai>=1.40,<2.0 ; extra == 'dev'
30
+ Requires-Dist: starlette>=0.40,<1.0 ; extra == 'dev'
31
+ Requires-Dist: uvicorn>=0.30,<1.0 ; extra == 'dev'
32
+ Requires-Dist: anyio>=4.4,<5.0 ; extra == 'dev'
33
+ Requires-Dist: langchain-core>=0.3,<1.0 ; extra == 'dev'
34
+ Requires-Dist: playwright>=1.59,<2.0 ; extra == 'dev'
35
+ Requires-Dist: langchain-core>=0.3,<1.0 ; extra == 'langchain'
36
+ Requires-Dist: langchain-openai>=0.3.35 ; extra == 'langchain'
37
+ Requires-Dist: langgraph>=1.0.1 ; extra == 'langchain'
38
+ Requires-Dist: starlette>=0.40,<1.0 ; extra == 'ui'
39
+ Requires-Dist: uvicorn>=0.30,<1.0 ; extra == 'ui'
40
+ Requires-Dist: anyio>=4.4,<5.0 ; extra == 'ui'
41
+ Maintainer: Ambuj Agrawal, Garima Luthra
42
+ Maintainer-email: Ambuj Agrawal <ambujagrawal741@gmail.com>, Garima Luthra <garimaluthra2198@gmail.com>
43
+ Requires-Python: >=3.12
44
+ Project-URL: Homepage, https://github.com/ambuj-krishna-agrawal/agent-lab
45
+ Project-URL: Repository, https://github.com/ambuj-krishna-agrawal/agent-lab
46
+ Project-URL: Issues, https://github.com/ambuj-krishna-agrawal/agent-lab/issues
47
+ Project-URL: Documentation, https://github.com/ambuj-krishna-agrawal/agent-lab#readme
48
+ Project-URL: Error reference, https://github.com/ambuj-krishna-agrawal/agent-lab/blob/main/docs/errors.md
49
+ Project-URL: Examples, https://github.com/ambuj-krishna-agrawal/agent-lab/tree/main/example
50
+ Project-URL: Changelog, https://github.com/ambuj-krishna-agrawal/agent-lab/blob/main/CHANGELOG.md
51
+ Provides-Extra: dev
52
+ Provides-Extra: langchain
53
+ Provides-Extra: ui
54
+ Description-Content-Type: text/markdown
55
+
56
+ # AgentLab
57
+
58
+ > Universal record-and-replay for LLM agents.
59
+
60
+ **Status:** pre-alpha, APIs will change.
61
+
62
+ AgentLab captures model calls, tools, state transitions, and timing into a
63
+ trace you can replay without hitting the network. It is built around a
64
+ framework-agnostic core and an HTTP capture layer that works with any SDK
65
+ that routes requests through `httpx`.
66
+
67
+ ## Overhead
68
+
69
+ Per-LLM-call cost of running inside `agentlab.record()`:
70
+
71
+ | metric | baseline | recorded | overhead |
72
+ |----------------|----------|-----------|-----------|
73
+ | latency p50 | 13.5 ms | 14.7 ms | +1.16 ms |
74
+ | latency p99 | 14.4 ms | 15.9 ms | +1.52 ms |
75
+
76
+ Measured against an in-process loopback HTTP server with a 10 ms upstream
77
+ delay (eliminates network jitter so the delta isolates SDK overhead:
78
+ HTTP capture, span emit, JSONL write+fsync, matcher, LLMSpan build).
79
+ Real LLM calls land in the 100 ms – 2000 ms range, so this works out to
80
+ under 1% wall-clock overhead in practice.
81
+
82
+ Reproduce with:
83
+
84
+ ```bash
85
+ uv run python scripts/bench_record_overhead.py --calls 200 --runs 5
86
+ ```
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ pip install agentic-lab # minimal SDK
92
+ pip install 'agentic-lab[ui]' # + Starlette UI server
93
+ ```
94
+
95
+ The PyPI distribution is **`agentic-lab`**; the importable Python
96
+ module is **`agentlab`**:
97
+
98
+ ```python
99
+ import agentlab as al
100
+ ```
101
+
102
+ For local development, this repo is `uv`-managed:
103
+
104
+ ```bash
105
+ git clone https://github.com/ambuj-krishna-agrawal/agent-lab.git
106
+ cd agent-lab
107
+ uv sync --all-extras --frozen
108
+ ```
109
+
110
+ Use `--frozen` by default so your environment matches `uv.lock` and CI.
111
+
112
+ ## Documentation
113
+
114
+ * [Quickstart](#quickstart) — five minutes from install to a replayable trace.
115
+ * [Provider coverage](#provider-coverage) — every supported LLM provider + how to add custom ones.
116
+ * [Error reference](docs/errors.md) — every `AGL-…` code with a remediation sentence (auto-generated from `src/agentlab/errors.py`).
117
+ * [Changelog](CHANGELOG.md) — version history.
118
+ * [`AGENTS.md`](AGENTS.md) — invariants and quality gates contributors must respect.
119
+ * [`CONTRIBUTING.md`](CONTRIBUTING.md) — human-contributor process.
120
+
121
+ ## Configuration
122
+
123
+ - Secrets live in `.env` (git-ignored). Copy `.env.example` and set the
124
+ provider keys you use.
125
+ - Non-secret defaults live in `src/agentlab/_defaults.toml` and can be
126
+ overridden by `AGENTLAB_*` environment variables.
127
+ - Full typed config lives in `src/agentlab/config.py`.
128
+
129
+ ## Quickstart
130
+
131
+ Five minutes from `pip install` to a trace you can replay without an
132
+ API key. The full runnable script lives at
133
+ [`example/quickstart.py`](example/quickstart.py); the inline version:
134
+
135
+ ```python
136
+ import os
137
+ import openai
138
+ import agentlab as al
139
+
140
+ client = openai.OpenAI(
141
+ api_key=os.environ["OPENROUTER_API_KEY"],
142
+ base_url="https://openrouter.ai/api/v1",
143
+ )
144
+
145
+ # 1. Record.
146
+ with (
147
+ al.record(agent_name="quickstart") as recording,
148
+ al.agent(name="quickstart", version="0"),
149
+ al.step(role=al.StepRole.EXECUTE),
150
+ ):
151
+ response = client.chat.completions.create(
152
+ model="openai/gpt-4o-mini",
153
+ messages=[{"role": "user", "content": "Reply with the single word 'ok'."}],
154
+ max_tokens=16,
155
+ )
156
+ print("model said:", response.choices[0].message.content)
157
+ print("trace at: ", recording.directory)
158
+
159
+ # 2. Replay — no network, no key.
160
+ with al.replay(str(recording.directory)) as session:
161
+ replay = client.chat.completions.create(
162
+ model="openai/gpt-4o-mini",
163
+ messages=[{"role": "user", "content": "Reply with the single word 'ok'."}],
164
+ max_tokens=16,
165
+ )
166
+ print("replay said:", replay.choices[0].message.content)
167
+ print("cache hits: ", session.cache_hits)
168
+ ```
169
+
170
+ ```bash
171
+ pip install 'agentic-lab[ui]' openai
172
+ export OPENROUTER_API_KEY=sk-or-...
173
+ python example/quickstart.py
174
+ agentlab serve --root ~/.agentlab/traces
175
+ # → http://127.0.0.1:7861/
176
+ ```
177
+
178
+ The `with al.agent(...)` and `al.step(...)` envelopes give the
179
+ auto-emitted `LLMSpan` a typed parent (the V4 schema forbids LLM
180
+ under bare RUN). Production agents normally establish these once
181
+ near their entrypoints and don't repeat them per-call — see
182
+ [`example/workflows/`](example/) for that shape.
183
+
184
+ ## Larger example agents
185
+
186
+ Three reference agents under [`example/`](example/) cover the
187
+ Anthropic [building-effective-agents](https://www.anthropic.com/research/building-effective-agents)
188
+ shapes:
189
+
190
+ | Folder | Shape | What it does |
191
+ |---|---|---|
192
+ | `workflows/` | Workflow (fixed code path) | Decompose → Wikipedia search → cite → LLM-as-judge → revise. |
193
+ | `autonomous/` | Autonomous (model picks each step) | LangGraph observe-plan-act loop that triages support tickets. |
194
+ | `hybrid/` | Workflow + autonomous sub-agent | Incident-response pipeline with autonomous investigation step. |
195
+
196
+ All three use OpenRouter via `langchain-openai`, real (or
197
+ realistic) tools, and produce traces directly into `example_traces/`
198
+ that `agentlab serve` can browse.
199
+
200
+ ## Provider coverage
201
+
202
+ Inside an `agentlab.record()` block AgentLab patches `httpx` transport
203
+ methods, so **every** SDK that routes through `httpx` (which is most
204
+ modern Python LLM SDKs) lands its raw exchange in `http.jsonl`. That
205
+ file is the source of truth for replay; the typed `LLMSpan` is a
206
+ best-effort view layered on top.
207
+
208
+ The built-in matchers turn recognised exchanges into typed `LLMSpan`s
209
+ out of the box:
210
+
211
+ | Provider | Endpoint(s) | Stream? |
212
+ |-----------------------------------|------------------------------------------------------|---------|
213
+ | OpenAI chat completions | `api.openai.com/v1/chat/completions` | yes |
214
+ | OpenAI Responses | `api.openai.com/v1/responses` | yes |
215
+ | OpenAI Embeddings | `api.openai.com/v1/embeddings` | n/a |
216
+ | Azure OpenAI chat completions | `*.openai.azure.com/openai/deployments/<dep>/chat/completions` | yes |
217
+ | Anthropic Messages | `api.anthropic.com/v1/messages` | yes |
218
+ | AWS Bedrock — Invoke | `bedrock-runtime.<region>.amazonaws.com/model/<id>/invoke[-with-response-stream]` | partial[^1] |
219
+ | AWS Bedrock — Converse | `bedrock-runtime.<region>.amazonaws.com/model/<id>/converse[-stream]` | partial[^1] |
220
+ | Google Gemini | `generativelanguage.googleapis.com/.../models/<m>:[stream]generateContent` | yes |
221
+ | Vertex AI — Gemini | `<region>-aiplatform.googleapis.com/.../models/<m>:[stream]generateContent` | yes |
222
+ | Vertex AI — Anthropic (Claude) | `<region>-aiplatform.googleapis.com/.../models/<m>:[stream]rawPredict` | yes |
223
+ | OpenRouter | `openrouter.ai/api/v1/chat/completions` | yes |
224
+ | Together AI | `api.together.{xyz,ai}/v1/chat/completions` | yes |
225
+ | Groq | `api.groq.com/openai/v1/chat/completions` | yes |
226
+ | Mistral | `api.mistral.ai/v1/chat/completions` | yes |
227
+ | Fireworks | `api.fireworks.ai/inference/v1/chat/completions` | yes |
228
+ | DeepInfra | `api.deepinfra.com/v1/openai/chat/completions` | yes |
229
+ | Perplexity | `api.perplexity.ai/chat/completions` | yes |
230
+
231
+ [^1]: Bedrock streaming uses AWS event-stream binary framing.
232
+ Buffered responses populate every LLMSpan field; streamed responses
233
+ record the request side and a `validation_errors` entry explaining
234
+ why the response side is empty. The raw bytes are still preserved
235
+ in `http.jsonl`.
236
+
237
+ ### Adding a custom or self-hosted provider
238
+
239
+ OpenAI-compatible hosts (vLLM, Ollama, your private gateway) need one
240
+ line:
241
+
242
+ ```python
243
+ import agentlab as al
244
+ from agentlab.llm.matchers.openai import HostPathMatcher
245
+
246
+ al.register_llm_provider(HostPathMatcher(
247
+ name="my-vllm",
248
+ host_suffix="llm.internal.example.com",
249
+ path_prefix="/v1/chat/completions",
250
+ ))
251
+ ```
252
+
253
+ For wholly different body shapes, subclass `agentlab.llm.LLMProviderMatcher`.
254
+
255
+ ### Pricing
256
+
257
+ The SDK is **token-only by default** — `LLMSpan.cost.usd` stays at
258
+ `0.0` and the span is annotated with `agentlab.llm.pricing.unknown=True`.
259
+ Provider list-prices change too often to bake into the SDK. Operators
260
+ who want USD computed on every span install their own table:
261
+
262
+ ```python
263
+ from agentlab.llm.pricing import PriceRow, StaticPriceTable, set_price_table
264
+
265
+ set_price_table(StaticPriceTable(rows=(
266
+ PriceRow("openai", "gpt-4o", 2.50, 10.00),
267
+ PriceRow("anthropic", "claude-3-5-sonnet*", 3.00, 15.00),
268
+ )))
269
+ ```
270
+
271
+ ### Strict mode for unrecognised exchanges
272
+
273
+ By default, exchanges that don't match any provider matcher log a
274
+ warning (one per `(trace, host)`) and the raw exchange remains in
275
+ `http.jsonl`. Power users can opt into stricter behaviour:
276
+
277
+ ```python
278
+ with al.record(strict_unknown_provider="raise"): # or "emit_op"
279
+ ...
280
+ ```
281
+
282
+ `"raise"` surfaces the gap as `UnknownLLMProviderError`; `"emit_op"`
283
+ records the call as a typed `OpSpan` so the trace tree is complete
284
+ even without a matcher.
285
+
286
+ ## UI and examples
287
+
288
+ Run the backend UI server against bundled traces:
289
+
290
+ ```bash
291
+ uv run agentlab --root example_traces serve --port 7861
292
+ ```
293
+
294
+ Optional frontend dev server with HMR:
295
+
296
+ ```bash
297
+ cd frontend
298
+ npm install
299
+ npm run dev
300
+ ```
301
+
302
+ The bundled runnable agents are seeded from `example/` and are available from
303
+ the Agents page when the server starts successfully.
304
+
305
+ ## Production deployment
306
+
307
+ The OSS UI server can be hosted on a single EC2 box behind Caddy, with a
308
+ separate Next.js + Clerk marketing/auth site on Vercel that redirects
309
+ authenticated users to it. See [`deploy/README.md`](deploy/README.md)
310
+ for the end-to-end runbook.
311
+
312
+ ## UI walkthrough
313
+
314
+ ### Dashboard
315
+ ![Dashboard](docs/assets/dashboard.png)
316
+
317
+ ### Traces list
318
+ ![Traces list](docs/assets/traces-list.png)
319
+
320
+ ### Trace detail
321
+ ![Trace detail](docs/assets/trace-detail.png)
322
+
323
+ ### Agents
324
+ ![Agents](docs/assets/agents.png)
325
+
326
+ ### Settings
327
+ ![Settings](docs/assets/settings.png)
328
+
329
+ ## Development
330
+
331
+ Run the local quality gate:
332
+
333
+ ```bash
334
+ bash scripts/check.sh
335
+ ```
336
+
337
+ Equivalent commands:
338
+
339
+ ```bash
340
+ uv run ruff check .
341
+ uv run ruff format --check .
342
+ uv run mypy
343
+ uv run pytest tests/unit tests/integration -n auto --dist=worksteal
344
+ ```
345
+
346
+ ## Testing
347
+
348
+ Current test tiers:
349
+
350
+ - `tests/unit/`: hermetic unit tests (no real network).
351
+ - `tests/integration/`: in-process integration tests with mocked HTTP where needed.
352
+
353
+ For live-provider smoke runs, use the runnable examples in `example/` through
354
+ their CLIs or the UI Agents page.
355
+
356
+ ## Project layout
357
+
358
+ ```text
359
+ agentlab/
360
+ ├── src/agentlab/
361
+ │ ├── __init__.py # public API surface
362
+ │ ├── cli.py # `agentlab` console entry point
363
+ │ ├── config.py # typed settings
364
+ │ ├── recorder.py # public `record()` context manager
365
+ │ ├── _defaults.toml # bundled non-secret defaults
366
+ │ ├── _proto/ # generated protobuf bindings (private)
367
+ │ ├── bridges/ # export bridges (e.g. OTel GenAI)
368
+ │ ├── core/ # recording primitives
369
+ │ ├── io/ # trace IO + HTTP capture
370
+ │ ├── integrations/ # framework adapters
371
+ │ ├── llm/ # provider-agnostic LLM client
372
+ │ ├── replay/ # deterministic replay engine
373
+ │ ├── storage/ # JSONL + protobuf stores
374
+ │ ├── ui/ # Starlette UI server + DTO mapping
375
+ │ ├── pytest.py # pytest plugin
376
+ │ └── promote.py # replay-test scaffold generator
377
+ ├── frontend/ # React SPA for the UI server
378
+ ├── example/ # bundled runnable agent seeds
379
+ ├── proto/agentlab/v1/trace.proto
380
+ ├── scripts/ # check, proto regen, UI screenshot helpers
381
+ ├── tests/{unit,integration}/
382
+ └── uv.lock
383
+ ```
384
+
385
+ ## License
386
+
387
+ Apache 2.0 — see [`LICENSE`](LICENSE).
@@ -0,0 +1,114 @@
1
+ agentlab/__init__.py,sha256=3zvy7-k5XhkCt5lh7JNzWv4XBOwouhU6Q61Z_Z_lBI0,6624
2
+ agentlab/_defaults.toml,sha256=4ZiKWuIAfHNXGKwAYHmJLOZEAcyMXP4qKyPNhF3z_UI,1563
3
+ agentlab/_proto/__init__.py,sha256=YC-1s_6NBP6cFuzrFxwDb5ABbZ7PLKUNK4mhKLIDNB8,873
4
+ agentlab/_proto/trace_pb2.py,sha256=UYob3SWs_--5nExTOXaucKthU4yNoY40aeBydERbUOE,24399
5
+ agentlab/_proto/trace_pb2.pyi,sha256=-GsesuKpz83MW9-vw8GIeP70-F5f-2_cZR-GiuBv3ws,43677
6
+ agentlab/bridges/__init__.py,sha256=UmItrTpLS8Ts6QGdxpmcfdnuJgBHkevgl98H2l89_yc,312
7
+ agentlab/bridges/otel_genai.py,sha256=rs5FIpO5G71oUFegSdwOfu7pCe0ICB2Hudz7bghSObg,11774
8
+ agentlab/cli.py,sha256=n7Q0uER-IilVyKnfFXuI0B3mJtspRWdrkitoXpHQYkU,22715
9
+ agentlab/config.py,sha256=RB-nTHBBLYPkWZAS2QVoPeg0iHdBmnCxA986zc1JTSU,10039
10
+ agentlab/core/__init__.py,sha256=tfXhuXjc2UE8774gqlOU57iKanLjhHK74HW3TKkA-Uo,5390
11
+ agentlab/core/_clock.py,sha256=MNBAIEpljsFEuMKQNB2JKf_gI35tmY_1xk4Q6qkTHlI,1449
12
+ agentlab/core/_fmt.py,sha256=sJkilTnPYeJADAvrtWJ0WW6tvdoEs5lkQFD5mZwDzbM,2538
13
+ agentlab/core/_replay_seam.py,sha256=aRpkeIaXVabbIq3llP-FzRRAN0muB9zRxvZhoY88lxU,4134
14
+ agentlab/core/agent.py,sha256=_y8ZAmRV9mrGFEB6PwNK4oEp3pSNe8Nm-dwEZoNq8SY,5985
15
+ agentlab/core/attributes.py,sha256=4WiTz1HKAT5iqWRQVw2EmERfIL6Rc5GCRSg0RjsCc-Y,3612
16
+ agentlab/core/budget.py,sha256=Z5SZBFRi3zhg-RtqYZBu5ajSUTe2Ze4UnB4zgvev130,1030
17
+ agentlab/core/context.py,sha256=Hn2MGJb1X-RPUx3NDwQck2meJOXQU1uT78IvQhKYJv0,23906
18
+ agentlab/core/continuation.py,sha256=DY3f7TWbSLEAOsKfM6xs6wMhi7eJQ5UC7hajaPsd2aY,6091
19
+ agentlab/core/cost.py,sha256=OdfzTI4As2AOUyME85EkOW0eLCjXDN3QG_5kYzw2oZo,3294
20
+ agentlab/core/determinism.py,sha256=Sz051_cMrjpvULEDfBfDBK3YzAmfkBNma3G-LTvOMiM,37459
21
+ agentlab/core/env.py,sha256=dILP06rJ4Nb8cwwgH6MkvXVS75HNSLJCzIO4nggEIJ0,14017
22
+ agentlab/core/eval.py,sha256=4SSIhlVQJtxmn26ERvsZqH_wC4T2fvr9IEkDD1k3Gts,5773
23
+ agentlab/core/guardrail.py,sha256=5wt6_4dppvX8QvOVQ1UwJ425xVpnu-rqtzt2piZzFC4,6669
24
+ agentlab/core/handles.py,sha256=l0ApK0QyjcZoi9WHC1o1PkSJeAqgHNWR8m-tq-AJVJo,17837
25
+ agentlab/core/handoff.py,sha256=XVaL9LbM50dha0XjVmT0fKyuARWWf8mT_NhiVbdR3Yk,12226
26
+ agentlab/core/ids.py,sha256=mysbbHJIQLJ8UgITY_J-Xuv95Zn7tA9kGNfBdgWZTzM,5096
27
+ agentlab/core/link.py,sha256=yf3eL6COWiZ0CVxLR4AJB4HbJZyYdqmiYcKQpnjIl8o,5185
28
+ agentlab/core/llm.py,sha256=Nt9pb14jpFzrR-v2xTG4H2MFKG7NHmMlvRxm7pDOK5k,19300
29
+ agentlab/core/memory.py,sha256=gsmVcCrXpR9EwNMF_WL9oRy2lIFnWDoMGv2ndT7PD7k,4119
30
+ agentlab/core/message.py,sha256=ae71C0_i6QoxAsUBFyNqESmXOgonT0eE3xfKj8Qc8dw,6231
31
+ agentlab/core/op.py,sha256=YpfvEU20xkc6EcEfrG3ZTEyqDwW0Hd0X2Q6EL-YUbbk,6641
32
+ agentlab/core/op_names.py,sha256=fTepVlA6eiot0ZNTR2Me1vAtRuar21k2uYPnrpmqg1I,1000
33
+ agentlab/core/retrieval.py,sha256=v8ztQB-556zZQJwhUsak3nBp0WcX36w1nyzchPLOM8k,4297
34
+ agentlab/core/run.py,sha256=4SLdT3yNUCzE2fwjUzfxwbcXPnnNpa4ZzxJcyTMJwk4,11156
35
+ agentlab/core/span.py,sha256=rRoHC_6yDe6Hkr5wAT-PDc5C0ZLJcxfc8FqfiSIRzWw,28267
36
+ agentlab/core/span_event.py,sha256=z5DTW5gv-h2S5rr9YouS20bf-iAf7BoAdHITfxfjNrk,11299
37
+ agentlab/core/status.py,sha256=2K40x4yLruzRd8U2RDJIooxb-s52JJ-678BPdUZrGO8,1969
38
+ agentlab/core/step.py,sha256=eCJzVZTzoWrW-v_emgOSjtu97e1AcmpFVWaef0XjxEM,27253
39
+ agentlab/core/tool.py,sha256=3j34Pu-NyP0NK7v-VyMcTun1lxanlMWmx0U48oyAt0A,10291
40
+ agentlab/core/types.py,sha256=18AAtx53XUjQtr8KYCvoZOxnWKftTpAlCOiNqpjUS5M,866
41
+ agentlab/errors.py,sha256=52L7XK8lZ10XmEZeDzDWnvf8HBRdnC9m52CrRHdCAlQ,26157
42
+ agentlab/integrations/__init__.py,sha256=K6pX0lzMViGWuuVhcJ4y39CBgNudEJRrAiKgffhyWus,209
43
+ agentlab/integrations/langchain/__init__.py,sha256=fqotiLXgaYzOBWiNuJpNgWblDU5GIW7F2qbCZnwTql4,584
44
+ agentlab/integrations/langchain/_callbacks.py,sha256=Hgq2IW639nUd5z-_7OGggQzp-_FpPSQ3hmth1f8R1NY,11849
45
+ agentlab/integrations/langchain/_helpers.py,sha256=vSAyMpfCGtqgi8iDTwD3kbZ1Jmc0DEuTj6-idpQk-sY,4841
46
+ agentlab/io/__init__.py,sha256=c-wTE1hZK4AWegovRvPTYStHpiv5mkDK2t9JMarEXKI,690
47
+ agentlab/io/format.py,sha256=ENH-_yGEGGy_T_ZxdfabLnl3ignvvU3bFKNWYC9LNmI,10396
48
+ agentlab/io/http_capture.py,sha256=lsDfRVfN43OGotCYoexu58qGkmY847IJb4UIm02cNRc,38976
49
+ agentlab/io/http_format.py,sha256=fcg_y3-aAOr8xT13ondwCz7PdV3waBO9ByUhkfS35FI,16669
50
+ agentlab/io/otel_attributes.py,sha256=hgzpHd-fUGqyjcByFobgnrRjcTn_8D4JatJDIvA_QxY,15973
51
+ agentlab/io/proto/__init__.py,sha256=Kd_mQlD2lKZGDljhQVkF9GQa5YjyGxxRjr29lprK3TU,561
52
+ agentlab/io/proto/codec.py,sha256=gQt5iL5yEGvWuVEmFadrfySNlQXVQzG8ngrFeZxNnow,49023
53
+ agentlab/io/proto/framing.py,sha256=3rjR8K-fH_q6kv0oanoTEz28fHfRzxDr2SIl0ucADj4,5437
54
+ agentlab/io/proto/reader.py,sha256=P6o4w-o8KSXlirTCZPZt8sCj8dia4CCVysVBbMBJZak,6672
55
+ agentlab/io/proto/writer.py,sha256=zof1WIK4HOH3Goyhn3blSzd0vvFcxel0Lz7rj0m3fCo,9493
56
+ agentlab/io/reader.py,sha256=TiJC3Onp5PWnsjGo9IfdBCDo2oeemJbbgxozaw9nXio,8749
57
+ agentlab/io/redaction.py,sha256=LNcalp-g9JHpXJIZxIptYLF_U0CqKCTU0T24BnuqYOQ,13324
58
+ agentlab/io/writer.py,sha256=HQGbi-WuUhIvUN9ZSIHj_TJil1Hf9oEpUm3zqv3UW2U,14765
59
+ agentlab/llm/__init__.py,sha256=rED-jBb5AQNECjXCQWcVY0pzpoXYxcFAtntCr9ZCTeE,2608
60
+ agentlab/llm/_autoemit.py,sha256=-fkX3Mqmwugax8UClG0buLwJ3l5ZOhDSJJjUjBAdsaA,19711
61
+ agentlab/llm/base.py,sha256=kFdrXGPP9PGKHNAwXWdlhCyqGXum1z1zYW1oIEJfY5w,12762
62
+ agentlab/llm/errors.py,sha256=Hv_TRpQzsesofbwL4RSCiRE27X0sKr5VJC_IumxUxlM,1421
63
+ agentlab/llm/factory.py,sha256=NIhmbjJ5fQQYgDkZ6FmJVRFku63b-WY8MqdrC62Lh-Q,2634
64
+ agentlab/llm/matchers/__init__.py,sha256=hvOVK_o9uc9gdU-mohV1SzcZOEtlsttiWK91aeDyy9k,4026
65
+ agentlab/llm/matchers/_common.py,sha256=TP21lT_rE9YjuzkDiCWeO9Q2ar2h20mo7tPH3q3xjHw,14276
66
+ agentlab/llm/matchers/anthropic.py,sha256=OfL5sKqwe2OWcFfmCpKp4X7xdRm1_sS-2copIkEADrI,18526
67
+ agentlab/llm/matchers/bedrock.py,sha256=Syf4aon6OYr1ULFx_u_oXrx0bKtR4pZSeSUF2r3k1KY,19529
68
+ agentlab/llm/matchers/google.py,sha256=hMYaQgDrf6tEtt6WwsAcZbIVXLcQ82NWwusxg2iptvk,20605
69
+ agentlab/llm/matchers/openai.py,sha256=hQmCI58ju9s0fyntJyEgxv_d-35dYxG0f7rQRNCJQJ8,44179
70
+ agentlab/llm/pricing.py,sha256=npXF9w8_BFFI31OELOJq6FgaGAL8SZ_ATumnhQdS77A,9180
71
+ agentlab/llm/providers/__init__.py,sha256=WJKhKq8v2F7mLm22Z2-GDUi9ZPk0LnS1WNiFpkFNllg,134
72
+ agentlab/llm/providers/openrouter.py,sha256=UV8DhcUUizjEunDzrWQKJhx4rnClQuDFvk6MRJxz5-c,16481
73
+ agentlab/llm/types.py,sha256=ttQmaXFx9YKk4Uw4F8FHQNIc7ZwQEBjc7n1laIu500w,18123
74
+ agentlab/promote.py,sha256=tCizxGbENsdJzJBCWQ3pVpIlJBnfLULRaqit9eCxjr8,10137
75
+ agentlab/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
+ agentlab/pytest.py,sha256=jO4oWsooBaRZRft2KPuBF-f0TwPcDCe2GmXscumjsHU,9222
77
+ agentlab/recorder.py,sha256=y5jzA_CYFGWP5FFlaPiHomy0mY9SaEt1cKzU4P8mlSA,37724
78
+ agentlab/replay/__init__.py,sha256=N0_POLMx4fI-9HBVYEQaRmYN0h08WcMOMX9PknKS6dY,3082
79
+ agentlab/replay/api.py,sha256=Vo8728f1lTtJqBC2kHvJsZuVBN6nNaOLCVPDhbqsPoA,14533
80
+ agentlab/replay/cache.py,sha256=PY6L6FSM30YMCckzw2glAoXA-NpdnyNZGl6WvhoW_98,12705
81
+ agentlab/replay/context.py,sha256=AOLg20dAfr4kCc5BAFdtzSHL9VkkRh8XuEmF6Bqb_1U,695
82
+ agentlab/replay/diff.py,sha256=ygEbfewkYHZtVNgtgCPUOsfJyhNZIB9jhM2uSeVtNQU,10622
83
+ agentlab/replay/drift.py,sha256=phke7zzVKqzZp3I9U2hBGxr-WtkBIHsEx4F85t0p5zs,2916
84
+ agentlab/replay/session.py,sha256=SC68qO5gFgG0bSUp4Jhoj9iNWpuCTgfFJCg0E6mv3fM,11457
85
+ agentlab/storage/__init__.py,sha256=3lioqBKOVdl4uINznwU16tWwZiiWKlmpg0fixGmYkZM,1218
86
+ agentlab/storage/base.py,sha256=JenNksapfcscmy0nlTi__nFQ3F75LHqXZEDT4nJfMag,12533
87
+ agentlab/storage/factory.py,sha256=Lvv45OrsLd9iRaoRemN-NZVMAm9_JIzh5kvpguT4hzg,3472
88
+ agentlab/storage/jsonl_store.py,sha256=4Ge0zNLhJ0wrkFHC2nRFpXIBGie9-aqYhrKzcDQEQx8,21190
89
+ agentlab/storage/names.py,sha256=CqgY0Y8UTgvR41fTl1gbzpA6ZDHSmbld27Rs_vcb9DM,9016
90
+ agentlab/storage/proto_store.py,sha256=LP_SZH-2YClSOr10B5hGnHlMhTsXKFOq0wlvVP-i058,15128
91
+ agentlab/ui/README.md,sha256=CWqJszUuAwWWEKWJkC3NjSRiLPynjSyWoHvK_5nearM,3417
92
+ agentlab/ui/__init__.py,sha256=pMAAy-CqJT5hE9sviRqD1fcJZPQyFE9iOtvS_GX46Yw,528
93
+ agentlab/ui/_agents.py,sha256=lpQaWlZ_F4B58uxKKbj5JqLEIKWZL4ojEMxlG4skMuQ,16396
94
+ agentlab/ui/_assets/__init__.py,sha256=RdguPkDgHn3V-apOtXGuLwRAn6hTg1kONbmwszr38vg,358
95
+ agentlab/ui/_assets/dist/assets/index-DGnShqkT.js,sha256=soW-FKfqwiynYvHthadjCVszCUVz_UkaTyQyFJqhYLk,1168103
96
+ agentlab/ui/_assets/dist/assets/index-DqoRSI-a.css,sha256=oLZp3pr44pQaiNbs5gD_RGbR7zh375kdquu8NMj21TI,76047
97
+ agentlab/ui/_assets/dist/favicon.svg,sha256=njwHC7J9K48K5Ieye85Gb3My6AhuQXXjfeCGg4KtivE,501
98
+ agentlab/ui/_assets/dist/index.html,sha256=fy8oxhe3kinp7xI4ATJl1L-uatrpjrwAztxIxTbpYkI,943
99
+ agentlab/ui/_dto.py,sha256=YoPivy1gam3y7NXC9Z59c8ebnIHA3rgnrOYRJDwmGWY,8889
100
+ agentlab/ui/_errors.py,sha256=VUTnPtaNiM152xWDOVtpsxFb43Dyg8WiX_wAXREObkc,1512
101
+ agentlab/ui/_mapping.py,sha256=IgJGLMuRDxY5yRiu0L_jJZPTblchEGjf3NxDesXFSgk,11209
102
+ agentlab/ui/_runtime.py,sha256=WPi3j9QZYUWMW-wj9qkaZeLu3SClYTchxIisEWNUcmU,2390
103
+ agentlab/ui/_server/__init__.py,sha256=AepLSJRVpt9x7x2w2lD2J2cl2T17rO7sys7-dHwGjME,233
104
+ agentlab/ui/_server/agents.py,sha256=PusYJ28r_6-vR77X5stO85Kssv-TganXm9qi0Yu5ksk,15865
105
+ agentlab/ui/_server/agents_overview.py,sha256=XJj4EnJ61hARQyrAoyP-X9sp6andGlo6J_zCAakIHM0,8628
106
+ agentlab/ui/_server/app.py,sha256=TLDzhjM0AoreHbSCwMz7aeoYVmllvK-iIc-L6U2wHis,25499
107
+ agentlab/ui/_server/dashboard.py,sha256=eZ7XjG1DdXQ2hh5v17zK2NAzMWc3N4YOf0WxCEeJ5Sg,11537
108
+ agentlab/ui/_server/replay_runner.py,sha256=E8vLFC0E6muTi-UuqWsjym9tM49GWMxld0WcHQXlYO0,18657
109
+ agentlab/ui/_server/validation.py,sha256=apCQ2mUsBy4FfDXxTt1jAmuuTRKxHDy2-Y1NHuEKcII,2312
110
+ agentlab/ui/_server/watcher.py,sha256=f-HTYQ3OR6-cz7FwSEiyVxeQtY5fxXlbjwJFgGlV-RU,3954
111
+ agentic_lab-0.1.0.dist-info/WHEEL,sha256=fWriCkzqm-pffF5af4gJC9iI5FMFaJTuN9UxxxzOmdY,81
112
+ agentic_lab-0.1.0.dist-info/entry_points.txt,sha256=PwIuE3BapXbs1NgBjf8j0HtTHoGWvOIW53aYKQ6w8jU,87
113
+ agentic_lab-0.1.0.dist-info/METADATA,sha256=vmxExXXwWs807UgoIVoHzrkJAIFR8gh_qQtl09k2Zd0,14844
114
+ agentic_lab-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.14
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,6 @@
1
+ [console_scripts]
2
+ agentlab = agentlab.cli:main
3
+
4
+ [pytest11]
5
+ agentlab = agentlab.pytest
6
+