ciagent 0.6.0__tar.gz → 0.8.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.
- ciagent-0.8.0/CHANGELOG.md +264 -0
- ciagent-0.8.0/PKG-INFO +307 -0
- ciagent-0.8.0/README.md +264 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/pyproject.toml +3 -2
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/capture.py +35 -15
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/cli.py +769 -24
- ciagent-0.8.0/src/agentci/engine/check_generator.py +330 -0
- ciagent-0.8.0/src/agentci/engine/judge_audit.py +427 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/mock_runner.py +37 -5
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/parallel.py +50 -7
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/path.py +15 -3
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/reporter.py +269 -6
- ciagent-0.8.0/src/agentci/engine/stability.py +375 -0
- ciagent-0.8.0/src/agentci/examples/__init__.py +3 -0
- ciagent-0.8.0/src/agentci/examples/demo_spec.yaml +73 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/schema/spec_models.py +6 -2
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/templates/report.html.j2 +45 -0
- ciagent-0.6.0/CHANGELOG.md +0 -123
- ciagent-0.6.0/PKG-INFO +0 -156
- ciagent-0.6.0/README.md +0 -113
- ciagent-0.6.0/src/agentci/_version.py +0 -3
- {ciagent-0.6.0 → ciagent-0.8.0}/.gitignore +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/LICENSE +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/__init__.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/adapters/__init__.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/adapters/base.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/adapters/generic.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/adapters/langgraph.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/adapters/openai_agents.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/assertions.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/baselines.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/config.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/cost.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/diff_engine.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/__init__.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/correctness.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/cost.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/cost_estimator.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/diff.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/judge.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/metrics.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/results.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/runner.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/engine/span_assertions.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/exceptions.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/loader.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/mocks.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/models.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/py.typed +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/pytest_plugin.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/report.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/runner.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/schema/__init__.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/schema/agentci_spec.schema.json +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/schema/generate_schema.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/templates/__init__.py +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/templates/github_action.yml.j2 +0 -0
- {ciagent-0.6.0 → ciagent-0.8.0}/src/agentci/templates/pre_push_hook.sh.j2 +0 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.8.0] - 2026-07-06
|
|
9
|
+
|
|
10
|
+
### Added — Claude Code plugin (F5: your coding agent onboards and operates AgentCI)
|
|
11
|
+
- The repo is now a Claude Code plugin marketplace
|
|
12
|
+
(`/plugin marketplace add suniel12/AgentCI`, `/plugin install agentci@agentci`)
|
|
13
|
+
with two skills: **onboard** (write the runner, record goldens via
|
|
14
|
+
`bootstrap --yes`, generate + tighten the spec, verify with `test --runs 3`)
|
|
15
|
+
and **check** (run the right check after agent changes; route failures by
|
|
16
|
+
flip source; never weaken a correct check to go green)
|
|
17
|
+
- `agentci bootstrap --yes`: fully non-interactive golden recording (requires
|
|
18
|
+
`--queries`); bootstrap now runs the runner through the same TraceContext
|
|
19
|
+
capture path as `agentci test`, so **runners returning plain strings work**
|
|
20
|
+
(previously crashed on anything but a Trace)
|
|
21
|
+
- `--format json` output now includes the agent's `answer` text per query
|
|
22
|
+
(eng-review work item: JSON consumers need what the agent said, not just
|
|
23
|
+
verdicts; also unblocks JSON as a judge-audit answers source)
|
|
24
|
+
- Tests: skills are lint-gated — every `agentci` command and flag a skill
|
|
25
|
+
teaches is asserted to exist in the CLI, so skill docs cannot rot silently
|
|
26
|
+
|
|
27
|
+
### Fixed — from Codex cross-model review of this branch
|
|
28
|
+
- **Nested `TraceContext` no longer double-records or loses capture**: a
|
|
29
|
+
Trace-returning runner that uses `TraceContext` internally, wrapped again by
|
|
30
|
+
the executor, used to stack SDK patches (every LLM call recorded once per
|
|
31
|
+
wrapper) and its exit cleared the outer context entirely. Patches now install
|
|
32
|
+
only in the outermost context, and exits restore the enclosing context via
|
|
33
|
+
contextvar tokens. Affected `agentci test` as well as the new bootstrap path
|
|
34
|
+
- JSON `answer` field now uses the correctness layer's extractor (metadata →
|
|
35
|
+
last span output), so trace shapes the evaluator can grade also serialize
|
|
36
|
+
their answer instead of `null`
|
|
37
|
+
|
|
38
|
+
### Added — zero-key demo (`uvx ciagent test --mock --runs 3`)
|
|
39
|
+
- `agentci test --mock` with no `agentci_spec.yaml` in the working directory now
|
|
40
|
+
falls back to a bundled demo spec (8 synthetic support-agent queries), clearly
|
|
41
|
+
labeled as demo mode with synthetic data. An explicitly passed `--config` that
|
|
42
|
+
is missing remains an error — the fallback only applies to the default path
|
|
43
|
+
- Demo multi-run sessions simulate a pseudo-flaky agent by default with the new
|
|
44
|
+
`"spread"` style (one query breaks per run), so the aggregate score stays
|
|
45
|
+
constant while individual verdicts flip — the report the demo exists to show.
|
|
46
|
+
`AGENTCI_MOCK_FLAKY=0` turns the simulation off; non-demo specs are unaffected
|
|
47
|
+
(flakiness stays env-var opt-in, `"alternate"` style unchanged)
|
|
48
|
+
- Missing spec without `--mock` now exits with a hint pointing at both
|
|
49
|
+
`agentci init` and the zero-key demo command
|
|
50
|
+
|
|
51
|
+
### Changed — stability report hardening (pre-launch fixes from eng review)
|
|
52
|
+
- **Flip attribution now compares per-layer sub-verdicts first**: if every
|
|
53
|
+
deterministic check returned the same outcome across runs and only the LLM judge's
|
|
54
|
+
verdict changed, the flip is `judge-flake` even when the answer text was
|
|
55
|
+
paraphrased (previously mislabeled `agent-variance`)
|
|
56
|
+
- **New flip source `infra-error`**: a judge API failure counted as a fail no longer
|
|
57
|
+
reads as `judge-flake` — one transient hiccup must not say "fix your rubric"
|
|
58
|
+
- **Console shows observed facts only** (verdict history + pass rate); pass@k /
|
|
59
|
+
pass^k move to JSON output as clearly labeled estimates (at small k they restate
|
|
60
|
+
the pass rate)
|
|
61
|
+
- Duplicate query texts in a spec are flagged (they merge into one stability
|
|
62
|
+
record); queries missing from some runs are marked `partial (k/N runs)`
|
|
63
|
+
- `agentci run` (legacy suite runner) now prints a deprecation warning pointing at
|
|
64
|
+
`agentci test`; removal planned for 0.9.0
|
|
65
|
+
- Removed stale `src/agentci/_version.py` (said 0.1.0; version comes from package
|
|
66
|
+
metadata)
|
|
67
|
+
|
|
68
|
+
## [0.7.0] - 2026-07-05
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
#### KB-Derived Fact Checks — `agentci generate-checks`
|
|
73
|
+
Mines the knowledge base for hard facts (prices, rates, SKUs, versions,
|
|
74
|
+
explicit quantities) and proposes them as deterministic assertions on
|
|
75
|
+
existing spec queries. One LLM call at authoring time; the checks run
|
|
76
|
+
deterministically forever at zero cost.
|
|
77
|
+
|
|
78
|
+
- **Brittleness gate**: every candidate is validated against recorded golden
|
|
79
|
+
answers before it is offered — a check that would fail a known-good answer
|
|
80
|
+
is rejected automatically with the failing answer shown
|
|
81
|
+
- Only non-paraphrasable facts; prose facts become variant sets
|
|
82
|
+
(`any_expected_in_answer`), never single literal strings; only
|
|
83
|
+
`any_expected_in_answer` / `not_in_answer` / `regex_match` are proposed
|
|
84
|
+
- Candidates without a golden answer are `unvalidated` and never
|
|
85
|
+
auto-accepted, even with `--yes`; interactive review for everything else
|
|
86
|
+
- Merge never overwrites user-written assertions; `.bak` backup on write;
|
|
87
|
+
`--dry-run` mode
|
|
88
|
+
- New module `agentci.engine.check_generator`; 21 new tests
|
|
89
|
+
|
|
90
|
+
#### Judge Audit — `agentci judge-audit`
|
|
91
|
+
Meta-evaluation of the LLM judge against ground truth you already have,
|
|
92
|
+
re-scoring recorded golden baselines (the agent is never re-run):
|
|
93
|
+
|
|
94
|
+
- **Mode 1 — judge vs. deterministic checks**: independent verdicts on the
|
|
95
|
+
same recorded answer; reports the disagreement matrix. The killer row:
|
|
96
|
+
answers the judge PASSED that a deterministic fact-check FAILED
|
|
97
|
+
(shared-context judge blindness, detected automatically)
|
|
98
|
+
- **Mode 2 — retest stability** (`--repeats K`, default 3): same answer
|
|
99
|
+
judged K times; verdict flips on identical input are the judge's noise floor
|
|
100
|
+
- **Mode 3 — hand labels** (`--labels FILE`): agreement + Cohen's κ against
|
|
101
|
+
human review, with standard trust thresholds
|
|
102
|
+
- Scoped claim stated in the report itself: measured on fact-checkable
|
|
103
|
+
queries; one-directional (disqualifying) signal for judgment-only queries
|
|
104
|
+
- Verdicts: TRUSTWORTHY / NEEDS CALIBRATION / UNRELIABLE (exit 1) /
|
|
105
|
+
ERROR when the judge never ran (exit 2 — a judge that couldn't run is
|
|
106
|
+
never scored)
|
|
107
|
+
- `--sample N` cost cap; console + JSON output
|
|
108
|
+
- New module `agentci.engine.judge_audit`; 27 new tests
|
|
109
|
+
|
|
110
|
+
#### Stability Report — `agentci test --runs N`
|
|
111
|
+
A stable suite score can hide per-query verdict flips: the aggregate holds
|
|
112
|
+
because the errors move around. `--runs N` executes the whole suite N times
|
|
113
|
+
and reports what a single run cannot show:
|
|
114
|
+
|
|
115
|
+
- Per-query verdict history (✅❌✅), pass rate, pass@k and pass^k estimates
|
|
116
|
+
- Suite score per run printed side by side with the queries that flipped
|
|
117
|
+
- **Flip-source attribution** — every flip is labelled:
|
|
118
|
+
- `agent-variance`: the agent's output changed → fix the agent
|
|
119
|
+
- `judge-flake`: same output, the LLM judge changed its verdict → fix the eval
|
|
120
|
+
- `mixed`: near-identical paraphrase with a judge configured — not guessed
|
|
121
|
+
Attribution rests on a structural fact: deterministic checks cannot flip on
|
|
122
|
+
identical output, so identical answer + tools + flipped verdict = judge.
|
|
123
|
+
- Exit semantics: flaky-but-passing exits 0 (warnings only); queries failing
|
|
124
|
+
in EVERY run exit 1; `--fail-on-flaky` escalates flips to exit 1
|
|
125
|
+
- Works in every format: console section, GitHub `::warning` annotations,
|
|
126
|
+
`stability` block in JSON, stability card in the HTML report
|
|
127
|
+
- Mock mode support: `AGENTCI_MOCK_FLAKY=1 agentci test --mock --runs 3`
|
|
128
|
+
demonstrates the report with zero API keys
|
|
129
|
+
- New module `agentci.engine.stability` (`build_stability_report`,
|
|
130
|
+
`StabilityReport`, `QueryStability`, `FlipSource`); 21 new tests
|
|
131
|
+
|
|
132
|
+
### Changed
|
|
133
|
+
- **`expected_tools` now asserts by default**: a missing expected tool produces a WARN
|
|
134
|
+
(tool recall gates at 1.0 unless `min_tool_recall` explicitly loosens it). Previously,
|
|
135
|
+
without `min_tool_recall`, a recall of 0.0 displayed as PASS with a checkmark.
|
|
136
|
+
- **`expected_tools: []` now asserts that no tools are called**: an explicit empty list
|
|
137
|
+
produces a WARN if the agent called any tool. Previously it was silently skipped.
|
|
138
|
+
- `agentci doctor` no longer reports numpy as a required dependency (it was never used
|
|
139
|
+
by AgentCI, so every fresh install showed a false failure).
|
|
140
|
+
|
|
141
|
+
### Docs
|
|
142
|
+
- README: fixed the quickstart spec example (was missing the required `agent:` field),
|
|
143
|
+
added CI badge, "Check facts in code" section, docs index
|
|
144
|
+
- Rewrote `docs/quickstart.md`, `docs/ci-cd.md`, `docs/cost-tracking.md`, and
|
|
145
|
+
`docs/golden-traces.md` to match the current `agentci test` workflow
|
|
146
|
+
- Fixed dead clone URLs in CONTRIBUTING.md and quickstart
|
|
147
|
+
- Removed unused demo GIF variants and cast recordings (6 files, ~2 MB)
|
|
148
|
+
|
|
149
|
+
## [0.6.0] - 2026-03-05
|
|
150
|
+
|
|
151
|
+
### Added
|
|
152
|
+
|
|
153
|
+
#### `final_output` Auto-Capture
|
|
154
|
+
- `TraceContext._auto_extract_final_output()` called in `__exit__()` — automatically extracts the agent's answer from traces
|
|
155
|
+
- Extraction priority: LangGraph state messages > span `output_data` (string) > span `output_data` (dict with `content`/`message`/`text`/`output` keys) > last LLM call `output_text`
|
|
156
|
+
- Manual `trace.metadata["final_output"]` still takes precedence (no overwrite)
|
|
157
|
+
- LangGraph adapter: auto-sets `final_output` from last AI message in `parse_state()`
|
|
158
|
+
- OpenAI Agents adapter: auto-sets `final_output` from last span output in `on_trace_end()`
|
|
159
|
+
|
|
160
|
+
#### `agentci calibrate` Command
|
|
161
|
+
- Runs N sample queries against the live agent, measures actual metrics, shows Rich comparison table
|
|
162
|
+
- Updates spec budgets with headroom: +50% for LLM/tool calls, +100% for tokens/cost
|
|
163
|
+
- Flags: `--samples N` (default 2), `--dry-run`, `--yes`, `--spec PATH`
|
|
164
|
+
|
|
165
|
+
#### Strict Tool Sequence Assertions
|
|
166
|
+
- `PathSpec.expected_tool_sequence: Optional[list[str]]` — strict ordered tool call check
|
|
167
|
+
- Mismatch = WARN (soft warning) with position-level diff via `_format_sequence_diff()`
|
|
168
|
+
|
|
169
|
+
#### HTML Trace Report
|
|
170
|
+
- Self-contained `report.html.j2` Jinja2 template with dark theme
|
|
171
|
+
- Summary dashboard (pass/fail/warn counts, total cost)
|
|
172
|
+
- Per-query cards with status badges, answer preview, three-layer details
|
|
173
|
+
- Collapsible trace tree with JS toggle
|
|
174
|
+
- Available via `agentci test --format html --output report.html` or `agentci report -i results.json`
|
|
175
|
+
|
|
176
|
+
### Changed
|
|
177
|
+
- `max_llm_calls` default in spec generator raised from 8 to 10 (better headroom for real agents)
|
|
178
|
+
- `max_llm_calls` fallback in mock runner raised from 3 to 10
|
|
179
|
+
- Calibrate command floor raised from 8 to 10
|
|
180
|
+
- `--format` choices in `test` and `eval` commands now include `html`
|
|
181
|
+
- `--output / -o` option added to `test` and `eval` commands for HTML file path
|
|
182
|
+
- `agentci report` command fully implemented (was stub) — converts JSON results to HTML
|
|
183
|
+
- 22 new tests added (570 total, up from 548 in v0.5.1)
|
|
184
|
+
|
|
185
|
+
## [0.5.0] - 2026-03-01
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
|
|
189
|
+
#### Three-Layer Evaluation Engine
|
|
190
|
+
- **Correctness layer** (Layer 1 — hard fail): keyword matching, LLM-as-a-judge, safety checks, hallucination checks, regex/exact match, JSON schema validation
|
|
191
|
+
- **Path layer** (Layer 2 — soft warn): tool trajectory validation, loop detection (default `max_loops=3`), routing assertions, handoff expectations
|
|
192
|
+
- **Cost layer** (Layer 3 — soft warn): token budgets, cost caps, LLM call limits, latency thresholds
|
|
193
|
+
- `runner.py` orchestrates all three layers per query
|
|
194
|
+
- `parallel.py` for parallel query execution across specs
|
|
195
|
+
|
|
196
|
+
#### OR-Logic Keywords
|
|
197
|
+
- `any_expected_in_answer` field — at least one keyword must match (complementing `expected_in_answer` which requires all)
|
|
198
|
+
|
|
199
|
+
#### LLM Judge Enhancements
|
|
200
|
+
- `context_file` support in `JudgeRubric` — doc-grounded judging against reference documents
|
|
201
|
+
- `refutes_premise` flag — injects built-in premise-correction rubric for trick questions
|
|
202
|
+
|
|
203
|
+
#### Span Assertions
|
|
204
|
+
- `SpanAssertionSpec` schema model for span-level assertions
|
|
205
|
+
- `Span.attributes: dict[str, Any]` — OTel-style span-level data propagation
|
|
206
|
+
- Span-level LLM judge support
|
|
207
|
+
|
|
208
|
+
#### Mock Testing Mode
|
|
209
|
+
- `agentci test --mock` — generates synthetic traces, zero API cost
|
|
210
|
+
- `mock_runner.py` — synthetic trace generation from spec expectations
|
|
211
|
+
- `--golden-file` flag — load Q&A pairs from JSON/CSV for mock mode
|
|
212
|
+
|
|
213
|
+
#### Cost Estimator
|
|
214
|
+
- `cost_estimator.py` — pre-execution cost estimates with pricing table
|
|
215
|
+
- Cost estimate shown before live test runs; `--yes`/`-y` skips confirmation
|
|
216
|
+
|
|
217
|
+
#### CLI Improvements
|
|
218
|
+
- `agentci init --generate` — AI-assisted spec generation with guided interview
|
|
219
|
+
- `agentci doctor` — health-check command (spec, runner, API keys, deps, CI)
|
|
220
|
+
- Scan-first flow: auto-scan project before questions, show summary
|
|
221
|
+
- Agent type auto-detected via `_detect_agent_type_from_code()`
|
|
222
|
+
- Skeleton template generation with TODO placeholders for zero-API-key usage
|
|
223
|
+
- Context-aware "Next Steps" based on mode (mock vs live)
|
|
224
|
+
- Non-interactive flags: `--kb-path`, `--mode`
|
|
225
|
+
|
|
226
|
+
#### Diff Engine
|
|
227
|
+
- Three-tier diff engine for baseline comparison
|
|
228
|
+
- 11 `DiffType` categories including `ROUTING_CHANGED`, `GUARDRAILS_CHANGED`
|
|
229
|
+
- `agentci diff` CLI command
|
|
230
|
+
|
|
231
|
+
#### Reporting
|
|
232
|
+
- GitHub annotations with budget cap (`MAX_INLINE_ANNOTATIONS = 10` for warnings; errors uncapped)
|
|
233
|
+
- JSON output format
|
|
234
|
+
- Prometheus metrics export
|
|
235
|
+
|
|
236
|
+
#### Trace Helpers
|
|
237
|
+
- `Trace.called(tool)` / `never_called(tool)` / `loop_count(tool)` — readable assertion helpers
|
|
238
|
+
- `Trace.cost_under(usd)` / `llm_calls_under(n)` — budget assertion helpers
|
|
239
|
+
- `langgraph_trace(agent_name)` — context manager shortcut for LangGraph
|
|
240
|
+
- `TraceContext.attach(state)` — alias for `attach_langgraph_state()`
|
|
241
|
+
|
|
242
|
+
#### Adapters
|
|
243
|
+
- OpenAI Agents SDK adapter (`openai_agents.py`)
|
|
244
|
+
- LangGraph adapter (`langgraph.py`)
|
|
245
|
+
|
|
246
|
+
#### Other
|
|
247
|
+
- `python-dotenv` added as core dependency
|
|
248
|
+
- Deep KB sampling: 2000 chars/file for spec generation
|
|
249
|
+
- Progressive spec building: smoke queries (3) then full queries (10-12)
|
|
250
|
+
- Pytest plugin entry point (`pytest11: agentci`)
|
|
251
|
+
- GUARDRAIL span type, HANDOFF span type
|
|
252
|
+
|
|
253
|
+
### Changed
|
|
254
|
+
- `PathSpec.max_loops` now defaults to `3` (was `None`)
|
|
255
|
+
- Development status upgraded from Alpha to Beta
|
|
256
|
+
- Package version bumped to 0.5.0
|
|
257
|
+
|
|
258
|
+
## [0.4.1] - 2026-02-20
|
|
259
|
+
|
|
260
|
+
### Added
|
|
261
|
+
- Initial project structure and core models
|
|
262
|
+
- Basic trace capture and assertion framework
|
|
263
|
+
- CLI scaffolding with `agentci init`
|
|
264
|
+
- PyPI publishing as `ciagent`
|
ciagent-0.8.0/PKG-INFO
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ciagent
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: Continuous Integration for AI Agents. Catch cost spikes and logic regressions before production.
|
|
5
|
+
Project-URL: Documentation, https://github.com/suniel12/AgentCI#readme
|
|
6
|
+
Project-URL: Repository, https://github.com/suniel12/AgentCI.git
|
|
7
|
+
Project-URL: Issues, https://github.com/suniel12/AgentCI/issues
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agents,ai,ci-cd,llm,regression,testing
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Framework :: Pytest
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Software Development :: Testing
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: click>=8.0
|
|
17
|
+
Requires-Dist: jinja2>=3.0
|
|
18
|
+
Requires-Dist: opentelemetry-api>=1.20
|
|
19
|
+
Requires-Dist: opentelemetry-sdk>=1.20
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Requires-Dist: pytest>=7.0
|
|
22
|
+
Requires-Dist: python-dotenv>=0.19
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: anthropic>=0.20; extra == 'all'
|
|
27
|
+
Requires-Dist: jsonschema>=4.0; extra == 'all'
|
|
28
|
+
Requires-Dist: langgraph>=0.1; extra == 'all'
|
|
29
|
+
Requires-Dist: openai>=1.0; extra == 'all'
|
|
30
|
+
Provides-Extra: anthropic
|
|
31
|
+
Requires-Dist: anthropic>=0.20; extra == 'anthropic'
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
36
|
+
Provides-Extra: jsonschema
|
|
37
|
+
Requires-Dist: jsonschema>=4.0; extra == 'jsonschema'
|
|
38
|
+
Provides-Extra: langgraph
|
|
39
|
+
Requires-Dist: langgraph>=0.1; extra == 'langgraph'
|
|
40
|
+
Provides-Extra: openai
|
|
41
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# AgentCI
|
|
45
|
+
|
|
46
|
+
**Pytest-native regression testing for AI agents.** Catch routing changes, tool call drift, and cost spikes before production.
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/ciagent/)
|
|
49
|
+
[](https://github.com/suniel12/AgentCI/actions/workflows/ci.yml)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
[](AGENTS.md)
|
|
52
|
+
|
|
53
|
+
You changed a prompt. Your agent broke in production. Three days later, a user complained. You had no tests, no diff, no idea what went wrong.
|
|
54
|
+
|
|
55
|
+
Works with OpenAI, Anthropic, and LangGraph. Runs inside pytest.
|
|
56
|
+
|
|
57
|
+
## See It in 30 Seconds
|
|
58
|
+
|
|
59
|
+
No install, no API keys, no config — one command runs a bundled demo suite three times on synthetic traces:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uvx ciagent test --mock --runs 3
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Run 1/3: 7/8 passed
|
|
67
|
+
Run 2/3: 7/8 passed
|
|
68
|
+
Run 3/3: 7/8 passed
|
|
69
|
+
|
|
70
|
+
────────────────────────────────────────────────────────────
|
|
71
|
+
Stability Report
|
|
72
|
+
────────────────────────────────────────────────────────────
|
|
73
|
+
Suite score across 3 runs: 88% / 88% / 88% ← looks stable
|
|
74
|
+
|
|
75
|
+
⚠️ FLAKY — 3/8 queries flipped verdicts across runs: ← is not
|
|
76
|
+
"What's your return window?" ❌✅✅ pass_rate=0.67 source: agent-variance
|
|
77
|
+
"Do you ship internationally?" ✅❌✅ pass_rate=0.67 source: agent-variance
|
|
78
|
+
"How do I reset my password?" ✅✅❌ pass_rate=0.67 source: agent-variance
|
|
79
|
+
|
|
80
|
+
Flip sources: 3 agent-variance (fix the agent) │ 0 judge-flake (fix the eval)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The aggregate score is identical every run. Three of the eight verdicts underneath it flipped. A single-run eval score would never tell you — the stability report does, and attributes every flip to the layer that caused it. (The demo simulates a flaky agent; point it at your own with the spec below.)
|
|
84
|
+
|
|
85
|
+
## Add to Your Project
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install ciagent
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Write your golden queries — what should your agent handle, and what should it refuse?
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# agentci_spec.yaml
|
|
95
|
+
agent: my-agent
|
|
96
|
+
# runner: any function that takes a query string and returns a response
|
|
97
|
+
runner: my_app.agent:run_for_agentci
|
|
98
|
+
queries:
|
|
99
|
+
- query: "How do I install AgentCI?"
|
|
100
|
+
correctness:
|
|
101
|
+
any_expected_in_answer: ["pip install", "ciagent"]
|
|
102
|
+
path:
|
|
103
|
+
expected_tools: [retrieve_docs]
|
|
104
|
+
cost:
|
|
105
|
+
max_llm_calls: 8
|
|
106
|
+
|
|
107
|
+
- query: "What's the CEO's favorite restaurant?"
|
|
108
|
+
correctness:
|
|
109
|
+
not_in_answer: ["restaurant", "favorite"]
|
|
110
|
+
path:
|
|
111
|
+
expected_tools: [] # expect no tools called for out-of-scope queries
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Run:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
agentci test --mock # start here: zero-cost with synthetic traces
|
|
118
|
+
agentci test # run live against your real agent
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`agentci test` evaluates each query through 3 layers — correctness, path, and cost:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
============================================================
|
|
125
|
+
|
|
126
|
+
Query: How do I install AgentCI?
|
|
127
|
+
Answer: To install AgentCI, you can use pip with the following command:
|
|
128
|
+
pip install ciagent. Make sure you have Python 3.10 or later.
|
|
129
|
+
|
|
130
|
+
✅ CORRECTNESS: PASS
|
|
131
|
+
✓ Found keywords: "pip install ciagent"
|
|
132
|
+
✓ LLM judge passed (score: 5 ≥ 0.6)
|
|
133
|
+
📈 PATH: PASS
|
|
134
|
+
✓ Tool recall: 1.000 (expected: [retrieve_docs])
|
|
135
|
+
✓ Tool precision: 0.500
|
|
136
|
+
✓ No loops detected
|
|
137
|
+
💰 COST: PASS
|
|
138
|
+
✓ LLM calls: 8 ≤ max 8
|
|
139
|
+
|
|
140
|
+
============================================================
|
|
141
|
+
|
|
142
|
+
Query: What Python version does AgentCI require and what frameworks does it support?
|
|
143
|
+
Answer: AgentCI currently does not specify a required Python version
|
|
144
|
+
in the provided context, so I don't have that information...
|
|
145
|
+
|
|
146
|
+
❌ CORRECTNESS: FAIL
|
|
147
|
+
• Expected '3.10' not found in answer
|
|
148
|
+
📈 PATH: PASS
|
|
149
|
+
✓ Tool recall: 1.000 (expected: [retrieve_docs])
|
|
150
|
+
✓ Loops: 1 ≤ max 3
|
|
151
|
+
💰 COST: PASS
|
|
152
|
+
✓ LLM calls: 4 ≤ max 5
|
|
153
|
+
|
|
154
|
+
============================================================
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Don't have golden queries yet? `agentci init --generate` scans your code and generates a starter spec.
|
|
158
|
+
|
|
159
|
+
## A stable score is not a stable system
|
|
160
|
+
|
|
161
|
+
Run the identical eval three times and you can get 96% / 95% / 96% — rock solid — while
|
|
162
|
+
individual queries flip verdicts every run. The aggregate holds because the errors move
|
|
163
|
+
around. `--runs N` shows what a single run can't:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
agentci test --runs 3
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
Run 1/3: 18/19 passed
|
|
171
|
+
Run 2/3: 18/19 passed
|
|
172
|
+
Run 3/3: 18/19 passed
|
|
173
|
+
|
|
174
|
+
────────────────────────────────────────────────────────────
|
|
175
|
+
Stability Report
|
|
176
|
+
────────────────────────────────────────────────────────────
|
|
177
|
+
Suite score across 3 runs: 95% / 95% / 95%
|
|
178
|
+
|
|
179
|
+
⚠️ FLAKY — 2/19 queries flipped verdicts across runs:
|
|
180
|
+
"What's your return window?" ✅❌✅ pass_rate=0.67 source: agent-variance (answer changed)
|
|
181
|
+
"Do you sell gift cards?" ❌✅✅ pass_rate=0.67 source: judge-flake (same answer, verdict flipped)
|
|
182
|
+
|
|
183
|
+
Flip sources: 1 agent-variance (fix the agent) │ 1 judge-flake (fix the eval) │ 0 infra-error (retry) │ 0 mixed
|
|
184
|
+
|
|
185
|
+
Stability verdict: FLAKY
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Every flip is attributed to its source, so it's a routed work item, not a scary number:
|
|
189
|
+
**agent-variance** means the agent produced different output (fix the prompt, retrieval, or
|
|
190
|
+
temperature); **judge-flake** means the output — or every deterministic check's outcome —
|
|
191
|
+
was identical but the LLM judge changed its mind (fix the rubric, or replace the judge with
|
|
192
|
+
a deterministic check); **infra-error** means a judge API call failed (retry, fix nothing).
|
|
193
|
+
Attribution is structural, not guessed: deterministic checks cannot flip on identical
|
|
194
|
+
output, and per-layer sub-verdicts are compared across runs. The console shows observed
|
|
195
|
+
facts; pass@k/pass^k estimates live in the JSON output, labeled as estimates.
|
|
196
|
+
|
|
197
|
+
Flaky-but-passing exits 0 so adoption won't break your CI; add `--fail-on-flaky` when
|
|
198
|
+
you're ready to gate on it. Try it with zero API keys:
|
|
199
|
+
`AGENTCI_MOCK_FLAKY=1 agentci test --mock --runs 3`. Details: [docs/stability.md](docs/stability.md).
|
|
200
|
+
|
|
201
|
+
## Audit the judge itself
|
|
202
|
+
|
|
203
|
+
An LLM judge that shares your agent's context inherits your agent's blind spots: when
|
|
204
|
+
retrieval comes up empty, the agent answers from nothing — and the judge, reading the same
|
|
205
|
+
nothing, passes it. `judge-audit` measures your judge against ground truth you already have,
|
|
206
|
+
by re-scoring recorded baselines (the agent is never re-run):
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
agentci judge-audit
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
1. **Judge vs. deterministic checks** — the disagreement matrix. The row that matters:
|
|
213
|
+
answers the judge PASSED that a hard fact-check FAILED.
|
|
214
|
+
2. **Retest stability** — the same answer judged `--repeats` times; flips on identical
|
|
215
|
+
input are the judge's own noise floor.
|
|
216
|
+
3. **Hand labels** (`--labels`) — agreement + Cohen's κ against your own review.
|
|
217
|
+
|
|
218
|
+
The claim is deliberately one-directional: a judge that fails where you *can* check it
|
|
219
|
+
shouldn't be trusted where you can't. Verdict: `TRUSTWORTHY` / `NEEDS CALIBRATION` /
|
|
220
|
+
`UNRELIABLE`. Details: [docs/judge-audit.md](docs/judge-audit.md).
|
|
221
|
+
|
|
222
|
+
## Check facts in code. Save the judge for judgment.
|
|
223
|
+
|
|
224
|
+
Most agent failures that matter involve a hard fact — a product name, a price, a version number. Those are checkable deterministically, for free. And an LLM judge grading against the same context as your agent inherits your agent's blind spots: when retrieval comes up empty, the agent answers from nothing and the judge — reading the same nothing — passes it.
|
|
225
|
+
|
|
226
|
+
So AgentCI runs deterministic checks first and treats the judge as the last resort, not the default:
|
|
227
|
+
|
|
228
|
+
1. **Fact checks in code** — `expected_in_answer`, `not_in_answer`, `regex_match`, `json_schema`. Zero LLM calls, zero flakiness, same verdict every run.
|
|
229
|
+
2. **Path checks** — did the agent call the tools it should have? A missing expected tool warns; a forbidden tool fails.
|
|
230
|
+
3. **Cost budgets** — LLM calls, tokens, dollars per query.
|
|
231
|
+
4. **LLM judge** (`llm_judge` rubrics, optional) — only for answers that genuinely need judgment, evaluated after every deterministic check has run.
|
|
232
|
+
|
|
233
|
+
Don't write the fact checks by hand — mine them from your knowledge base:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
agentci generate-checks
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
It extracts hard facts (prices, rates, SKUs, "30 days") as variant-set assertions, and
|
|
240
|
+
**validates every candidate against your recorded golden answers first** — a check that
|
|
241
|
+
would fail a known-good answer is rejected before you ever see it. One LLM call at
|
|
242
|
+
authoring time; the checks run free forever. Details: [docs/generate-checks.md](docs/generate-checks.md).
|
|
243
|
+
|
|
244
|
+
## Let your coding agent set it up
|
|
245
|
+
|
|
246
|
+
AgentCI ships as a Claude Code plugin. Two skills: **onboard** (writes the runner,
|
|
247
|
+
records golden baselines, generates the spec, verifies it) and **check** (runs the
|
|
248
|
+
right test after every change to your agent and routes failures by flip source).
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
/plugin marketplace add suniel12/AgentCI
|
|
252
|
+
/plugin install agentci@agentci
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Then ask your coding agent to "set up AgentCI for this repo." It records goldens with
|
|
256
|
+
`agentci bootstrap --yes` and verifies with `agentci test --runs 3` — no human CLI use
|
|
257
|
+
needed. The runner it writes is one function: `(query: str) -> str`; trace capture is
|
|
258
|
+
automatic.
|
|
259
|
+
|
|
260
|
+
## Demo
|
|
261
|
+
|
|
262
|
+
Here's a RAG agent demo where someone "optimizes for latency" by reducing retriever docs from 8 to 1. AgentCI catches the correctness regression:
|
|
263
|
+
|
|
264
|
+

|
|
265
|
+
|
|
266
|
+
## CLI
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
agentci init --generate # Scan project, generate test spec
|
|
270
|
+
agentci init # Generate GitHub Actions workflow + pre-push hook
|
|
271
|
+
agentci test --mock --yes # Zero-cost synthetic traces, CI-friendly (no keys, no prompts)
|
|
272
|
+
agentci test # Run 3-layer evaluation (correctness → path → cost)
|
|
273
|
+
agentci test --runs 3 # Stability report: verdict flips + flip-source attribution
|
|
274
|
+
agentci judge-audit # Audit the LLM judge against checks, retests, hand labels
|
|
275
|
+
agentci generate-checks # Mine KB facts into deterministic assertions (gated)
|
|
276
|
+
agentci test --format html -o report.html # HTML report with per-query details
|
|
277
|
+
agentci calibrate # Measure real agent metrics, auto-tune spec budgets
|
|
278
|
+
agentci doctor # Health check: spec, deps, API keys
|
|
279
|
+
agentci record <test> # Record golden baseline
|
|
280
|
+
agentci diff # Diff against baseline
|
|
281
|
+
agentci report -i results.json # Generate HTML report from JSON results
|
|
282
|
+
```
|
|
283
|
+
## Docs
|
|
284
|
+
|
|
285
|
+
- [Quickstart](docs/quickstart.md) — install to first green run
|
|
286
|
+
- [Stability testing](docs/stability.md) — `--runs N`, flip-source attribution
|
|
287
|
+
- [Judge audit](docs/judge-audit.md) — is your LLM judge lying to you?
|
|
288
|
+
- [Generate checks](docs/generate-checks.md) — mine KB facts into gated assertions
|
|
289
|
+
- [Writing tests](docs/writing-tests.md) — the full spec reference
|
|
290
|
+
- [Cost tracking](docs/cost-tracking.md) — budgets and spike detection
|
|
291
|
+
- [Golden traces](docs/golden-traces.md) — record baselines, diff regressions
|
|
292
|
+
- [CI/CD integration](docs/ci-cd.md) — GitHub Actions setup
|
|
293
|
+
- [LangGraph](docs/langgraph.md) — graph-based agent support
|
|
294
|
+
- [Metrics reference](docs/metrics_reference.md) — every metric, defined
|
|
295
|
+
|
|
296
|
+
## Why not just an LLM judge?
|
|
297
|
+
|
|
298
|
+
Judge-only evals are expensive, flaky, and blind to their own context. AgentCI is pytest-native regression testing: deterministic checks catch the factual failures, golden traces catch behavioral drift, cost budgets catch spend regressions — and the judge handles only what genuinely needs judgment. Mock mode (`agentci test --mock`) runs the whole suite with zero API keys and zero cost, so it can gate every PR.
|
|
299
|
+
|
|
300
|
+
## Contributing
|
|
301
|
+
|
|
302
|
+
[GitHub Issues](https://github.com/suniel12/AgentCI/issues) ·
|
|
303
|
+
[DemoAgents](https://github.com/suniel12/DemoAgents) — working examples for OpenAI, Anthropic, and LangGraph agents
|
|
304
|
+
|
|
305
|
+
Apache 2.0. If you build an agent and test it with AgentCI, I'd love to hear about it.
|
|
306
|
+
|
|
307
|
+
---
|