# Stratagem

Market research agent with document processing, web scraping, SEC filings, and financial analysis. Ships a research orchestrator plus four skills.

Status: active

## Install

```bash
claude plugin marketplace add tyroneross/RossLabs-AI-Toolkit
claude plugin install stratagem@rosslabs-ai-toolkit
```

## The Problem

Market research is five tools in a trench coat. You pull the 10-K from EDGAR, scrape the competitor's pricing page, extract numbers from a PDF, compute ratios in a spreadsheet, then write the memo. Each step has its own failure modes and nothing ties them together. Doing it as one-off prompts drops context between steps.

## What I Built

Stratagem runs research workflows that chain document processing, web scraping, SEC filings, and financial analysis under one orchestrator agent.

## Architecture

Stratagem runs on the Claude Agent SDK, not a custom orchestration framework — `stratagem.server` exposes 13 tools as a host-neutral MCP server, and a control agent built on the SDK's `query()` plans, delegates to specialist subagents, and tracks quality gates. The full pipeline — deterministic budget classifier → control agent → parallel specialist fan-out → file-based extraction handoff → synthesis → validation → deliverable — is described below, including which model runs at each stage, why, and where state lives.

```mermaid
flowchart LR
  A["CLI / plugin skill:<br/>research question"] --> B["Deterministic complexity classifier<br/>lean / standard / deep budget"]
  B --> C["Control agent<br/>Opus (default) or Sonnet, Claude Agent SDK"]
  C --> D["research-planner (Sonnet)<br/>task decomposition"]
  D --> E["Parallel fan-out (Sonnet subagents,<br/>capped by budget)"]
  E --> E1["data-extractor:<br/>parse_pdf / scrape_url / spreadsheet / pptx / docx"]
  E --> E2["financial-analyst:<br/>SEC EDGAR search + download"]
  E1 --> F["In-memory cache<br/>SHA256(tool+args), 5min TTL"]
  E2 --> F
  F --> G[("File extractions<br/>stratagem/extractions/")]
  G --> H["research-synthesizer /<br/>executive-synthesizer (Sonnet)"]
  H --> I["source-verifier / plan-validator /<br/>report-critic (Sonnet, budget-capped)"]
  I --> J["create_report / create_pptx /<br/>create_spreadsheet"]
  J --> K[("stratagem/reports/")]
  I -.-> L["after-action-analyst (Sonnet)"]
  L --> M[("Three-tier file memory:<br/>thread → topic → common")]
  M -.reused next run.-> C
```

## How It Works

1. A research question enters via the CLI (`python -m stratagem "..."`) or a Claude Code plugin skill (`research`, `extract-data`, `analyze-earnings`, `flowchart`).
2. Before any model runs, a deterministic keyword classifier (`_derive_delegation_budget`) scores the prompt on financial/comparison/web/document signals, length, and input-file count, then sets one of three operating envelopes — lean, standard, or deep — capping agent dispatches (3/5/7), parallel tasks (2/3/4), and validation passes (1/1/2). Runs that produce a deliverable file always force the planner and a `report-critic` pass, regardless of mode.
3. The control agent (Opus by default; Sonnet with `--fast` or `--model sonnet`) reads the budget and dispatches `research-planner` to decompose the question into a structured task plan.
4. The control agent fans out to specialist subagents in parallel, bounded by the budget's `max_parallel_tasks`: `data-extractor` calls `parse_pdf`, `scrape_url`, `read_spreadsheet`, `read_pptx`, `read_docx`, and `extract_images`; `financial-analyst` calls `search_sec_filings` and `download_sec_filing` against SEC EDGAR's public REST API directly (`data.sec.gov`, rate-limited to 8 req/sec under SEC's 10 req/sec cap, with exponential backoff on 429/5xx).
5. The five read-only extraction tools are wrapped in an in-memory cache keyed by `SHA256(tool_name + args)` with a 5-minute TTL, so a repeat request for the same PDF, URL, or spreadsheet within a session is served without a second fetch.
6. Each subagent writes its extraction to `stratagem/extractions/` as a markdown file — a file-based handoff, not a context pass, so synthesis reads from disk instead of replaying the raw extraction back through the model.
7. `research-synthesizer` and `executive-synthesizer` combine the extractions into a cited narrative; `flowchart-architect` and `design-agent` structure findings into slide or report layout when the run targets an artifact.
8. Validation runs up to the budget's `max_validation_passes`: `source-verifier` cross-checks claims against cited sources, `plan-validator` spot-checks subagent output against the original plan for drift, and `report-critic` scores completeness, accuracy, structure, and actionability — `report-critic` is mandatory whenever the run emits a file, independent of mode.
9. `create_report`, `create_pptx`, and `create_spreadsheet` write the final deliverable to `stratagem/reports/`; the control agent verifies the file exists at a non-zero size before reporting its absolute path back to the user.
10. `after-action-analyst` runs a post-run review and proposes memory updates or new agent specs; `create_specialist` can spawn a new subagent at runtime (defaults to Sonnet) if the planner hits a capability gap mid-run — the new agent is available for dispatch immediately.
11. Findings persist in a three-tier file-based memory, no database involved: thread (`.stratagem/threads/<id>/messages.jsonl` + a rolling `context.md`, per session) rolls up into topic (`.stratagem/topics/<id>/memory.json`, aggregated across threads on a subject) rolls up into common (`.stratagem/memory.json`, cross-topic). A store gets compacted once it passes 12 entries or ~6KB — LLM-summarized, with a deterministic fallback if that fails.

### Models

- **Control agent — Claude Opus (default), Sonnet with `--fast`/`--model sonnet`.** Runs the planning-and-delegation loop and holds the full tool allowlist; frontier model chosen here because it's the one component making judgment calls about what to delegate and when a run is done, not extracting or reformatting.
- **All 12 built-in subagents — Claude Sonnet** (`data-extractor`, `research-synthesizer`, `executive-synthesizer`, `financial-analyst`, `flowchart-architect`, `prompt-optimizer`, `research-planner`, `source-verifier`, `report-critic`, `after-action-analyst`, `plan-validator`, `design-agent`). Each does narrowly-scoped extraction, reformatting, or scoring work against a fixed prompt template — the source code's own inline comments call this out explicitly ("strong prompt compensates" for tasks like PPTX generation and synthesis reformatting), so a smaller model at lower cost/latency was chosen over Opus for every specialist.
- **Per-run and per-agent overrides.** `--model-override <agent>:<model>` lets any subagent run on `opus` or `haiku` instead of the Sonnet default; `create_specialist` defaults dynamically-spawned agents to Sonnet with the same override choice.
- **No embeddings, no vector search.** Memory retrieval is JSON/JSONL key lookup across the thread/topic/common tiers, not semantic search — there's no vector store in the stack.
- **Memory compaction is LLM-assisted with a deterministic backstop.** Large memory stores are summarized by an LLM call; `fallback_memory_compression` produces a rule-based summary (top N sources/findings/process items) if that call fails, so compaction never blocks on model availability.

## Tech stack

Python 3.12, Claude Agent SDK (`claude-agent-sdk`, MCP server + subagent orchestration), SEC EDGAR REST API via a custom `httpx` + BeautifulSoup4/lxml client (replaces the `edgartools` dependency), `pypdf` + `pdfplumber` (PDF), `python-docx` (Word), `python-pptx` (PowerPoint), `openpyxl` (Excel/CSV), LangSmith (optional tracing, `LANGSMITH_TRACING=true`, no-op otherwise). Storage is local filesystem only — `.stratagem/threads/`, `.stratagem/topics/`, `stratagem/extractions/`, `stratagem/reports/`, `stratagem/cache/` — with `fcntl` file locks guarding concurrent index writes; no database or vector store.

## Impact

The stack is Python, grounded in real document processing rather than LLM summarization of headers. SEC EDGAR integration pulls filings from the source, not from scraped summaries. The orchestrator pattern keeps state between steps, so the third question in a session builds on the first one's data.

## Results

The orchestrator coordinates four skills (`research`, `extract-data`, `analyze-earnings`, `flowchart`) against real sources: SEC EDGAR filings pulled directly rather than scraped summaries, and document/web extraction grounded in actual page and file content rather than LLM-summarized headers. State persists across steps within a session, so a later question in a multi-turn session reuses data gathered by earlier steps instead of re-deriving it.

⚠️ no benchmark yet — no measured latency, accuracy, or throughput figures exist for the orchestrator or its skills.

## Links

- [HTML project page](https://rosslabs.ai/projects/stratagem/)
- [Source code](https://github.com/tyroneross/stratagem)
