api-shakedown 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 (41) hide show
  1. api_shakedown-0.1.0/.gitignore +22 -0
  2. api_shakedown-0.1.0/LICENSE +21 -0
  3. api_shakedown-0.1.0/PKG-INFO +431 -0
  4. api_shakedown-0.1.0/README.md +384 -0
  5. api_shakedown-0.1.0/examples/petstore.yaml +135 -0
  6. api_shakedown-0.1.0/pyproject.toml +92 -0
  7. api_shakedown-0.1.0/src/api_shakedown/__init__.py +3 -0
  8. api_shakedown-0.1.0/src/api_shakedown/__main__.py +3 -0
  9. api_shakedown-0.1.0/src/api_shakedown/agents/__init__.py +1 -0
  10. api_shakedown-0.1.0/src/api_shakedown/agents/_common.py +36 -0
  11. api_shakedown-0.1.0/src/api_shakedown/agents/chaos.py +146 -0
  12. api_shakedown-0.1.0/src/api_shakedown/agents/contracts.py +176 -0
  13. api_shakedown-0.1.0/src/api_shakedown/agents/coordinator.py +211 -0
  14. api_shakedown-0.1.0/src/api_shakedown/agents/reviewer.py +301 -0
  15. api_shakedown-0.1.0/src/api_shakedown/agents/stubs.py +163 -0
  16. api_shakedown-0.1.0/src/api_shakedown/agents/testdata.py +146 -0
  17. api_shakedown-0.1.0/src/api_shakedown/chaos.py +451 -0
  18. api_shakedown-0.1.0/src/api_shakedown/chaos_control.py +54 -0
  19. api_shakedown-0.1.0/src/api_shakedown/cli.py +131 -0
  20. api_shakedown-0.1.0/src/api_shakedown/config.py +19 -0
  21. api_shakedown-0.1.0/src/api_shakedown/contracts.py +243 -0
  22. api_shakedown-0.1.0/src/api_shakedown/harness/__init__.py +26 -0
  23. api_shakedown-0.1.0/src/api_shakedown/mcp_server.py +218 -0
  24. api_shakedown-0.1.0/src/api_shakedown/pipeline.py +92 -0
  25. api_shakedown-0.1.0/src/api_shakedown/py.typed +0 -0
  26. api_shakedown-0.1.0/src/api_shakedown/spec/__init__.py +17 -0
  27. api_shakedown-0.1.0/src/api_shakedown/spec/chunking.py +32 -0
  28. api_shakedown-0.1.0/src/api_shakedown/spec/edge_cases.py +149 -0
  29. api_shakedown-0.1.0/src/api_shakedown/spec/loader.py +104 -0
  30. api_shakedown-0.1.0/src/api_shakedown/spec/models.py +78 -0
  31. api_shakedown-0.1.0/src/api_shakedown/spec/normalize.py +175 -0
  32. api_shakedown-0.1.0/src/api_shakedown/spec/refs.py +59 -0
  33. api_shakedown-0.1.0/src/api_shakedown/spec/samples.py +100 -0
  34. api_shakedown-0.1.0/src/api_shakedown/spec/schema_check.py +31 -0
  35. api_shakedown-0.1.0/src/api_shakedown/templates/__init__.py +1 -0
  36. api_shakedown-0.1.0/src/api_shakedown/templates/chaos_cli.py +92 -0
  37. api_shakedown-0.1.0/src/api_shakedown/templates/contract_runner.py +50 -0
  38. api_shakedown-0.1.0/src/api_shakedown/templates/robustness_runner.py +37 -0
  39. api_shakedown-0.1.0/src/api_shakedown/templates/shakedown_support.py +92 -0
  40. api_shakedown-0.1.0/src/api_shakedown/testdata.py +215 -0
  41. api_shakedown-0.1.0/src/api_shakedown/wiremock.py +273 -0
@@ -0,0 +1,22 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv/
7
+ venv/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .mypy_cache/
11
+ .coverage
12
+ htmlcov/
13
+
14
+ # secrets: never commit real keys
15
+ .env
16
+
17
+ # generated harnesses
18
+ shakedown-output/
19
+
20
+ .idea/
21
+ .vscode/
22
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anzar Ahsan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,431 @@
1
+ Metadata-Version: 2.5
2
+ Name: api-shakedown
3
+ Version: 0.1.0
4
+ Summary: Multi-agent generator of WireMock stubs, contract tests, and chaos scenarios from an OpenAPI spec.
5
+ Project-URL: Homepage, https://github.com/anzar-ahsan-commits/api-shakedown
6
+ Project-URL: Documentation, https://github.com/anzar-ahsan-commits/api-shakedown#readme
7
+ Project-URL: Issues, https://github.com/anzar-ahsan-commits/api-shakedown/issues
8
+ Project-URL: Changelog, https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/CHANGELOG.md
9
+ Author: Anzar Ahsan
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: chaos-engineering,contract-testing,langgraph,llm,mcp,openapi,wiremock
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Testing
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: agentpanel<0.2,>=0.1.0
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: openapi-spec-validator>=0.7
27
+ Requires-Dist: pyyaml>=6.0
28
+ Requires-Dist: typer>=0.12
29
+ Provides-Extra: anthropic
30
+ Requires-Dist: agentpanel[anthropic]<0.2,>=0.1.0; extra == 'anthropic'
31
+ Provides-Extra: cloud
32
+ Requires-Dist: agentpanel[cloud]<0.2,>=0.1.0; extra == 'cloud'
33
+ Provides-Extra: dev
34
+ Requires-Dist: agentpanel[cloud]<0.2,>=0.1.0; extra == 'dev'
35
+ Requires-Dist: build>=1.2; extra == 'dev'
36
+ Requires-Dist: mcp<3,>=2.3; extra == 'dev'
37
+ Requires-Dist: mypy>=1.11; extra == 'dev'
38
+ Requires-Dist: pytest>=8; extra == 'dev'
39
+ Requires-Dist: ruff>=0.6; extra == 'dev'
40
+ Requires-Dist: twine>=5; extra == 'dev'
41
+ Requires-Dist: types-pyyaml; extra == 'dev'
42
+ Provides-Extra: mcp
43
+ Requires-Dist: mcp<3,>=2.3; extra == 'mcp'
44
+ Provides-Extra: openai
45
+ Requires-Dist: agentpanel[openai]<0.2,>=0.1.0; extra == 'openai'
46
+ Description-Content-Type: text/markdown
47
+
48
+ # API Shakedown
49
+
50
+ **Give it an OpenAPI spec. Get back a ready-to-run test harness: WireMock stubs, contract
51
+ tests, robustness probes, and chaos scenarios, written by a team of LLM agents that
52
+ review each other's work.**
53
+
54
+ [![CI](https://github.com/anzar-ahsan-commits/api-shakedown/actions/workflows/ci.yml/badge.svg)](https://github.com/anzar-ahsan-commits/api-shakedown/actions/workflows/ci.yml)
55
+ [![PyPI](https://img.shields.io/pypi/v/api-shakedown.svg)](https://pypi.org/project/api-shakedown/)
56
+ [![Python](https://img.shields.io/pypi/pyversions/api-shakedown.svg)](https://pypi.org/project/api-shakedown/)
57
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/LICENSE)
58
+
59
+ Runs **locally on [Ollama](https://ollama.com) by default**: no API key, no data leaves
60
+ your machine. Cloud models (OpenAI, Anthropic) are bring-your-own-key. Available as a
61
+ CLI, a Docker image, and an **MCP server** so an AI assistant can drive it.
62
+
63
+ > Status: alpha (0.1.0). Works end to end on the example spec with a local 8B model.
64
+
65
+ ---
66
+
67
+ ## Contents
68
+
69
+ - [Why](#why)
70
+ - [Quick start](#quick-start)
71
+ - [What you get](#what-you-get)
72
+ - [How it works](#how-it-works)
73
+ - [Install](#install)
74
+ - [Usage](#usage)
75
+ - [Configuration](#configuration)
76
+ - [MCP server](#mcp-server)
77
+ - [Docker](#docker)
78
+ - [Architecture](#architecture)
79
+ - [Limitations](#limitations)
80
+ - [Roadmap](#roadmap)
81
+ - [Development](#development)
82
+ - [Contributing](#contributing)
83
+ - [License](#license)
84
+
85
+ ## Why
86
+
87
+ Teams that consume an API need three things that are tedious to write by hand and go
88
+ stale quickly:
89
+
90
+ 1. **A realistic mock** of the API to develop and test against.
91
+ 2. **Contract tests** that tell you when the real API stops matching its spec.
92
+ 3. **Failure drills**: what does your client do when the API is slow, flaky, rate
93
+ limited, returns garbage, or goes down?
94
+
95
+ API Shakedown generates all three from the spec you already have, and keeps them honest:
96
+ **the LLMs never write code that runs**. They propose *data* (response bodies, test
97
+ cases, failure scenarios, test records), and code validates every item against the
98
+ spec, feeds problems back to the model, and falls back to deterministic output when a
99
+ model cannot get it right. Without any model at all (`--offline`), every part still works.
100
+
101
+ ## Quick start
102
+
103
+ Prerequisites: Python 3.11+, Docker (for WireMock), and [Ollama](https://ollama.com) with
104
+ a model (`ollama pull qwen3:8b`) unless you use `--offline` or a cloud model.
105
+
106
+ ```bash
107
+ pip install api-shakedown
108
+ shakedown doctor # is the model ready?
109
+ shakedown run openapi.yaml --out my-harness # minutes on a local model
110
+ cd my-harness
111
+ docker compose up -d # WireMock with your stubs on :8080
112
+ pip install -r requirements.txt
113
+ SHAKEDOWN_SELECT_STATUS=1 pytest tests/test_contract.py
114
+ python chaos/chaos.py on flaky-start # now point your client at :8080
115
+ python chaos/chaos.py off
116
+ ```
117
+
118
+ Try it on the bundled example: `shakedown run examples/petstore.yaml --out petstore`.
119
+
120
+ A real run on the example spec with `qwen3:8b`:
121
+
122
+ ```text
123
+ Petstore 1.0.0: 5 operations (ollama / qwen3:8b)
124
+ Generating test data...
125
+ Test data ready (3 Pet).
126
+ Generating stubs, contract tests, and chaos scenarios...
127
+ stubs: done
128
+ contracts: done
129
+ chaos: done
130
+ review contracts: approved
131
+ review stubs: approved
132
+ review chaos: approved
133
+
134
+ Wrote 14 files to harness in 436s: 15 stubs, 11 contract cases, 11 chaos scenarios, 30 probes.
135
+ Next: cd harness && docker compose up -d (then see README.md)
136
+ ```
137
+
138
+ ## What you get
139
+
140
+ ```text
141
+ my-harness/
142
+ ├── README.md # generated: how to run it, every scenario, review notes
143
+ ├── docker-compose.yml # WireMock 3 serving the stubs (port: SHAKEDOWN_WIREMOCK_PORT)
144
+ ├── wiremock/mappings/ # stub mappings
145
+ ├── tests/
146
+ │ ├── test_contract.py # contract tests (cases in contract_cases.json)
147
+ │ └── test_robustness.py # malformed-request probes (cases in robustness_cases.json)
148
+ ├── chaos/
149
+ │ ├── chaos.py # switch failure scenarios on/off (standard library only)
150
+ │ └── chaos_scenarios.json
151
+ ├── data/dataset.json # test records and edge-case values per field
152
+ ├── requirements.txt # pytest, httpx, openapi-schema-validator
153
+ └── shakedown.json # manifest: counts, review outcome, generation notes
154
+ ```
155
+
156
+ | Part | What it does |
157
+ |---|---|
158
+ | **Stubs** | Every documented response of every operation. Known ids return their own record, unknown ids return the documented 404, and any other response can be requested with `X-Shakedown-Status: <status>`. |
159
+ | **Contract tests** | Happy paths, documented error statuses, and boundary values. Each checks the status code, `Content-Type`, and the body against the response schema. Run them against the stubs or a real deployment. |
160
+ | **Robustness probes** | Invalid bodies and parameters derived from the schemas (missing required fields, wrong types, out-of-range values, broken JSON). A robust server answers 4xx, never 5xx. |
161
+ | **Chaos scenarios** | Seven baseline failures every client should survive, plus scenarios the LLM targets at your API. |
162
+ | **Test data** | Realistic, consistent records per entity, shared by the stubs and the tests, plus edge-case values for every field. |
163
+
164
+ Baseline chaos scenarios:
165
+
166
+ | Scenario | What happens | A resilient client should |
167
+ |---|---|---|
168
+ | `total-outage` | Every endpoint returns 503 | Fail fast, back off, not hammer the API |
169
+ | `slow-responses` | Every response takes 3 s | Stay responsive |
170
+ | `timeouts` | Every response takes 30 s | Give up on its own and free resources |
171
+ | `connection-resets` | Connections are reset | Retry idempotent calls with backoff |
172
+ | `flaky-start` | First 2 calls fail with 503, then recover | Retry and succeed on the third attempt |
173
+ | `rate-limited` | First 3 calls return 429 | Honour `Retry-After` |
174
+ | `truncated-json` | Success bodies are cut off mid-JSON | Report a parse error, never crash |
175
+
176
+ LLM-targeted scenarios from a real run include *createPet fails 3 times with 503 then
177
+ recovers*, *listPets is rate limited*, and *getPet loses required fields*.
178
+
179
+ ## How it works
180
+
181
+ ```mermaid
182
+ flowchart LR
183
+ spec[/"OpenAPI spec"/] --> load["Load, validate,<br/>normalize, chunk"]
184
+ load --> data["Test data agent"]
185
+ data --> stubs["Stub agent"]
186
+ data --> contracts["Contract agent"]
187
+ data --> chaos["Chaos agent"]
188
+ stubs --> review{"Reviewer agent"}
189
+ contracts --> review
190
+ chaos --> review
191
+ review -- "blocker: revise with feedback" --> stubs
192
+ review -- "blocker" --> contracts
193
+ review -- "blocker" --> chaos
194
+ review -- "approved, or budget spent" --> coord["Coordinator"]
195
+ coord --> harness[/"Harness directory"/]
196
+ ```
197
+
198
+ 1. **Spec layer**: loads YAML/JSON from a path or URL, validates it (problems become
199
+ warnings), inlines `$ref`s safely, and splits operations into prompt-sized chunks so
200
+ large specs fit small models.
201
+ 2. **Test data agent** runs first: the stubs and tests share its records.
202
+ 3. **Stub, contract, and chaos agents** run in parallel.
203
+ 4. **Reviewer** judges each artifact. Blockers send it back to its author with the
204
+ feedback, for a bounded number of rounds; suggestions are kept as notes.
205
+ 5. **Coordinator** assembles the harness and its README, including anything the
206
+ reviewer still rejected when the revision budget ran out.
207
+
208
+ Every agent follows the same pattern, which is what keeps small local models reliable:
209
+
210
+ ```mermaid
211
+ sequenceDiagram
212
+ participant A as Agent
213
+ participant M as LLM
214
+ participant C as Code checks
215
+ A->>M: task + JSON schema (constrained decoding on Ollama)
216
+ M-->>A: proposal (bodies, cases, scenarios, records)
217
+ A->>C: validate against the spec
218
+ alt problems found
219
+ C-->>A: exact errors, e.g. "listPets 200: 'id' is a required property"
220
+ A->>M: fix these problems
221
+ M-->>A: corrected proposal
222
+ end
223
+ A->>A: keep valid items, fall back to deterministic ones for the rest
224
+ ```
225
+
226
+ Things code guarantees, so the model never has to:
227
+
228
+ - Request matching, URL patterns, priorities, and path-parameter types in the stubs.
229
+ - Response bodies valid against their schemas.
230
+ - Test inputs that route (valid path parameters, required query parameters), success
231
+ cases that use ids that exist, 404 cases that use ids that do not.
232
+ - Authentication from the spec's security schemes.
233
+ - Chaos scenarios that are internally consistent (a "flaky" failure must recover, a rate
234
+ limit is a 429, a partial outage leaves some endpoints up).
235
+ - Reviewer findings that cite real items, and blockers only on what the author controls.
236
+
237
+ ## Install
238
+
239
+ ```bash
240
+ pip install api-shakedown # local models via Ollama
241
+ pip install "api-shakedown[cloud]" # plus OpenAI and Anthropic
242
+ pip install "api-shakedown[mcp]" # plus the MCP server
243
+ ```
244
+
245
+ Or use the Docker image, which includes everything: see [Docker](#docker).
246
+
247
+ Generated harnesses need Docker (for WireMock) and Python for their tests.
248
+
249
+ ## Usage
250
+
251
+ ```text
252
+ shakedown doctor Check the LLM provider is reachable and ready
253
+ shakedown inspect SPEC [--json] Show the operations the agents will see
254
+ shakedown run SPEC [options] Generate a harness
255
+ shakedown version
256
+ ```
257
+
258
+ `shakedown run` options:
259
+
260
+ | Option | Default | |
261
+ |---|---|---|
262
+ | `--out PATH` | `shakedown-output` | Where to write the harness (refuses a non-empty directory) |
263
+ | `--offline` | off | No LLM: deterministic output in seconds |
264
+ | `--no-review` | review on | Skip the reviewer (about 3x faster on the example) |
265
+ | `--max-revisions N` | `1` | Review/revise rounds |
266
+ | `--force` | off | Write into a non-empty directory (only overwrites harness files) |
267
+ | `--provider`, `--model` | from settings | Override the LLM for this run |
268
+
269
+ Using the harness:
270
+
271
+ ```bash
272
+ docker compose up -d # stubs on http://localhost:8080
273
+ SHAKEDOWN_SELECT_STATUS=1 pytest tests/test_contract.py # against the stubs
274
+ python chaos/chaos.py list | on <scenario> | off # failure drills
275
+ SHAKEDOWN_TARGET_URL=https://api.example.com/v1 pytest tests # against a real server
276
+ ```
277
+
278
+ PowerShell: `$env:SHAKEDOWN_SELECT_STATUS = "1"; pytest tests/test_contract.py`.
279
+
280
+ ## Configuration
281
+
282
+ Settings come from environment variables or a `.env` file
283
+ (see [.env.example](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/.env.example)). Everything is optional.
284
+
285
+ | Variable | Default | |
286
+ |---|---|---|
287
+ | `SHAKEDOWN_PROVIDER` | `ollama` | `ollama`, `openai`, or `anthropic` |
288
+ | `SHAKEDOWN_MODEL` | per provider | `qwen3:8b`, `gpt-5-mini`, `claude-sonnet-5-5` |
289
+ | `SHAKEDOWN_OLLAMA_URL` | `http://localhost:11434` | Where Ollama runs |
290
+ | `SHAKEDOWN_BASE_URL` | | Endpoint override, e.g. an OpenAI-compatible server |
291
+ | `SHAKEDOWN_TIMEOUT` | 600 (Ollama) / 120 | Seconds per request |
292
+ | `SHAKEDOWN_CONTEXT_WINDOW` | `16384` | Ollama context size |
293
+ | `SHAKEDOWN_REASONING` | model default | Ollama: turn a reasoning model's thinking on/off |
294
+ | `SHAKEDOWN_AGENT_MODELS` | | Per-agent models, e.g. `{"reviewer": "anthropic:claude-sonnet-5-5"}` |
295
+ | `SHAKEDOWN_AGENT_REASONING` | thinking off for generators | Per-agent thinking, e.g. `{"reviewer": true}` |
296
+ | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` | | Bring your own key |
297
+
298
+ Mixing models works well: generate locally, review with a stronger cloud model:
299
+
300
+ ```bash
301
+ SHAKEDOWN_AGENT_MODELS='{"reviewer": "anthropic:claude-sonnet-5-5"}' shakedown run openapi.yaml
302
+ ```
303
+
304
+ Generated harnesses read `SHAKEDOWN_TARGET_URL`, `SHAKEDOWN_SELECT_STATUS`,
305
+ `SHAKEDOWN_API_KEY`, `SHAKEDOWN_BASIC_AUTH`, `SHAKEDOWN_TIMEOUT`, and
306
+ `SHAKEDOWN_WIREMOCK_PORT` / `SHAKEDOWN_WIREMOCK_URL`.
307
+
308
+ ## MCP server
309
+
310
+ `shakedown-mcp` (stdio) lets an MCP client such as Claude Code or Claude Desktop
311
+ generate harnesses and run failure drills:
312
+
313
+ | Tool | |
314
+ |---|---|
315
+ | `doctor` | Is the LLM provider ready? |
316
+ | `inspect_spec` | List a spec's operations and warnings |
317
+ | `generate_harness` | Generate a harness, with progress notifications |
318
+ | `list_chaos_scenarios` | Scenarios in a harness |
319
+ | `activate_chaos` / `deactivate_chaos` | Switch a scenario on/off in a running WireMock |
320
+
321
+ ```bash
322
+ pip install "api-shakedown[mcp]"
323
+ claude mcp add api-shakedown -- shakedown-mcp # Claude Code
324
+ ```
325
+
326
+ Other clients (`mcpServers` in their config):
327
+
328
+ ```json
329
+ {
330
+ "mcpServers": {
331
+ "api-shakedown": {
332
+ "command": "shakedown-mcp",
333
+ "env": { "SHAKEDOWN_PROVIDER": "ollama" }
334
+ }
335
+ }
336
+ }
337
+ ```
338
+
339
+ Pass absolute paths. Generating with a local model takes minutes; if your client gives up
340
+ on long tool calls, use `offline` or `review: false`, or raise its tool timeout.
341
+
342
+ ## Docker
343
+
344
+ ```bash
345
+ docker build -t api-shakedown .
346
+ docker run --rm -v "$PWD:/work" api-shakedown run /work/openapi.yaml --out /work/harness
347
+ docker run -i --rm -v "$PWD:/work" --entrypoint shakedown-mcp api-shakedown # MCP server
348
+ ```
349
+
350
+ The image reaches Ollama on the host at `host.docker.internal`. Details for Linux,
351
+ PowerShell, and cloud keys: [DOCKER.md](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/DOCKER.md).
352
+
353
+ ## Architecture
354
+
355
+ ```mermaid
356
+ flowchart TB
357
+ subgraph app["api-shakedown"]
358
+ cli["CLI: shakedown"] --> pipeline["pipeline"]
359
+ mcp["MCP server: shakedown-mcp"] --> pipeline
360
+ pipeline --> agents["agents: testdata, stubs, contracts,<br/>chaos, reviewer, coordinator"]
361
+ agents --> domain["spec, wiremock, contracts,<br/>chaos, testdata (code checks)"]
362
+ pipeline --> harness["harness writer + templates"]
363
+ end
364
+ subgraph core["agentpanel (reusable core)"]
365
+ workflow["Workflow: parallel specialists,<br/>cross-review, bounded revision"]
366
+ structured["structured output:<br/>validate, feed back, retry"]
367
+ llm["providers: Ollama, OpenAI, Anthropic"]
368
+ end
369
+ agents --> workflow
370
+ agents --> structured
371
+ structured --> llm
372
+ ```
373
+
374
+ The orchestration core is published separately as
375
+ [**agentpanel**](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/packages/agentpanel/README.md): a small, domain-agnostic library for
376
+ "specialists draft, reviewers critique, authors revise, a coordinator decides" workflows
377
+ on LangGraph. It never imports the application; a test enforces that.
378
+
379
+ ```text
380
+ packages/agentpanel/ # the reusable core (its own PyPI package)
381
+ src/api_shakedown/ # the application
382
+ spec/ # loading, validation, $ref resolution, edge cases, samples
383
+ agents/ # the six agents
384
+ templates/ # runners copied into every harness
385
+ examples/petstore.yaml # example spec
386
+ tests/ # offline tests; `-m live` for Ollama + Docker tests
387
+ ```
388
+
389
+ ## Limitations
390
+
391
+ - **Speed on local models**: a full run on the 5-operation example takes about 7 minutes
392
+ with `qwen3:8b`, most of it review; `--no-review` takes about 2.5 minutes.
393
+ - **Small reviewers are imperfect**: an 8B reviewer sometimes raises a false blocker,
394
+ which costs a revision round. Use a stronger model for the reviewer if you can.
395
+ - **Specs**: OpenAPI 3.0-3.2. Swagger 2.0 must be converted first; references to other
396
+ files are not followed; self-referencing schemas are not validated.
397
+ - **Stubs are static**: a create call returns a new record, but stubs do not keep state
398
+ between calls.
399
+ - **Probes against stubs** only cover operations that document a 4xx; they are meant for
400
+ real servers.
401
+ - Tested so far mainly on the bundled example. Reports from larger real-world specs are
402
+ very welcome.
403
+
404
+ ## Roadmap
405
+
406
+ - Larger real-world specs: batching and timing at 30+ operations
407
+ - Stateful stubs (WireMock response templating, created records visible to later calls)
408
+ - Auth-failure scenarios (401/403) and "valid but nasty input must not 5xx" probes
409
+ - Review of the test dataset
410
+ - More harness targets (k6 load profiles, Postman collections)
411
+
412
+ ## Development
413
+
414
+ ```bash
415
+ git clone https://github.com/anzar-ahsan-commits/api-shakedown.git
416
+ cd api-shakedown
417
+ python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
418
+ pip install -e packages/agentpanel -e ".[dev]"
419
+ ruff check . && ruff format --check . && mypy
420
+ pytest # offline: LLMs are faked, about 20 s
421
+ pytest -m live # also uses your local Ollama and Docker
422
+ ```
423
+
424
+ ## Contributing
425
+
426
+ Contributions are welcome: see [CONTRIBUTING.md](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/CONTRIBUTING.md). Security issues:
427
+ see [SECURITY.md](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/SECURITY.md).
428
+
429
+ ## License
430
+
431
+ [MIT](https://github.com/anzar-ahsan-commits/api-shakedown/blob/main/LICENSE) © 2026 Anzar Ahsan