# Agent Spec Writer

> A template and techniques for writing a clear spec before generating a new LangGraph agent. Use when the user says "build an agent", "write a LangGraph agent", "I need an agent that...", or before calling write_langgraph_agent / an equivalent code-generation tool. Returns a structured spec ready to feed into the tool or to code from by hand.

- **Type:** Skill
- **Install:** `agentstack add skill-kirill-sviridov-agent-dev-skills-agent-spec-writer`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [kirill-sviridov](https://agentstack.voostack.com/s/kirill-sviridov)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [kirill-sviridov](https://github.com/kirill-sviridov)
- **Source:** https://github.com/kirill-sviridov/agent-dev-skills/tree/main/plugins/agent-dev-skills/skills/agent-spec-writer

## Install

```sh
agentstack add skill-kirill-sviridov-agent-dev-skills-agent-spec-writer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Agent Spec Writer

> Use this BEFORE a code-generation step (e.g. `write_langgraph_agent(...)` from a local codegen MCP tool). The goal is to turn a vague ask ("I want an agent that...") into a complete spec the model can't reinterpret "its own way."

> **This skill is a codegen-tool add-on, but it is fully useful without one.** (Optional — the `write_langgraph_agent` calls below assume a local code-generation MCP tool; without it, write the spec using the same sections and code the agent yourself from it.) When there is no codegen tool, skip step 3 of the algorithm and item 1 of the Output check, and replace section 8 with inline notes on known patterns.

## When to use

- The user framed the task in one phrase and asked to "build an agent."
- You're about to call a codegen tool, but the spec in your head is fuzzy.
- The last generation produced "the wrong thing" — the typical cause is an under-specified spec.

## When NOT to use

- The task is a small edit to an existing agent (use `/debug-langgraph-agent` / edit directly).
- The stack isn't chosen yet — run `/agent-tech-chooser` first.
- It's not a LangGraph agent (e.g. a simple single-turn LLM call — write raw SDK straight away).

## Algorithm

1. **Confirm the stack = LangGraph.** If in doubt — run `/agent-tech-chooser` first.
2. **Run the user's request through the 9 sections below.** Each section must get a concrete answer. If the answer is "depends on the user" — ask a clarifying question **before** generating.
3. **Cross-check against RAG (if available):** `search_agent_knowledge(" example")` — find 1-2 close patterns and mention them in section 8 (optional — assumes a local knowledge-retrieval MCP tool; if there's no such tool, skip this and note the known pattern to lean on instead).
4. **Assemble the final spec** in the format below and feed it as `task=` into your codegen tool (or code it yourself from the spec).

## The 9 mandatory spec sections

```
## 1. Agent goal (1-2 sentences)
What it does from the user's point of view. No architecture details.
Example: "Classifies a user comment as safe/spam/toxic and returns the
matching response handler."

## 2. Input / output
- Input: 
- Output: 
Example:
- Input: {"comment": str}
- Output: {"label": Literal["safe","spam","toxic"], "response": str}

## 3. State schema (hint, not final code)
List the keys, types, and whether reducers are needed.
Example:
- messages: list[AnyMessage], reducer = add_messages
- label: str | None (overwrite)
- artifacts: list[dict], reducer = operator.add

## 4. Tools (if any)
For each tool: name, signature, what it does, when to call it, what it returns.
If there are no tools — write "Tools: none".
Example:
- check_service_health(service: str) -> dict — pings the service, returns
  {"status": "up"|"down", "latency_ms": int}. Call when the user asks about
  availability.

## 5. Control flow (pattern)
One of: ReAct loop (create_agent) / workflow with conditional_edges /
supervisor + specialists / swarm / map-reduce (Send) / HITL with interrupt.
Briefly describe "how execution flows."

## 6. Model provider
- init_chat_model(":")
- Do NOT invent the model name or pull it "from memory" — it goes stale faster
  than the skill. Resolution order: 1) the user specified it explicitly;
  2) it's in the project config/env (`AGENT_MODEL` or an existing constant) —
  take it from there; 3) otherwise ask the user, offering to confirm the
  provider's current small model. In the spec, reference the env/constant,
  not a literal. If the project goes through an OpenAI-compatible proxy,
  `OPENAI_BASE_URL` / `OPENAI_API_KEY` come from the project environment —
  don't hardcode them in the spec.

## 7. Production flags
- Checkpointer: InMemorySaver (dev/test only) / AsyncPostgresSaver (prod) / none
- Durability: sync / async (default) / exit — for HITL with interrupt don't pick exit
- HITL: interrupt in which node / none
- Structured output: response_format= directly (auto → ProviderStrategy
  on models with native support; ToolStrategy() — for the rest) / none
- Streaming: graph.stream(stream_mode="messages") / none
- Node timeouts: add_node(..., timeout=N) or TimeoutPolicy(run_timeout=, idle_timeout=)
  (LangGraph 1.2+, async nodes only) / none
- Retry: is a retry decorator needed around the LLM call
- LangSmith tracing: on (LANGSMITH_TRACING=true) / off

## 8. Reference patterns from RAG (if RAG is available)
1-3 lines on which pattern cards from your knowledge store apply.
Example: "See distilled/repo__react-agent.md for the ReAct structure,
distilled/lc_blog_multi_agent_workflows.md for conditional_edges."
If RAG is unavailable — 1-3 lines on which known pattern to lean on.

## 9. Acceptance criteria / evals
3-5 "input → expected output" pairs — these double as test cases for the generation.
Example:
- {"comment": "great service!"} → label="safe"
- {"comment": "BUY CRYPTO AT THIS LINK"} → label="spam"
- {"comment": "you're an idiot"} → label="toxic", response contains a polite refusal
```

## Output style (what you feed into the codegen tool)

Pass it as one large `task=` parameter with all 9 sections in markdown. Code-generation models read structured specs far better than "build an agent that classifies."

**Do NOT** include in `task=`:
- Finished code (there's nothing to copy — the model should write it).
- Long quotes from docs (RAG will pull those in itself).
- The history of previous iterations ("here's what didn't work last time..." — that's for `/debug-langgraph-agent`).

## Anti-patterns when writing a spec

- **"Build an agent for the X task."** Too vague. The model will invent its own state, tools, and control flow — and almost always guess wrong.
- **"Use LangGraph."** That's not a spec. Which pattern inside LangGraph?
- **Listing tools without signatures.** "Use tools for search and for calling the API" — the model invents its own `def search(query)` signatures that later don't line up.
- **Not specifying the state structure.** The model forgets the reducer, adds extra fields, or makes messages a plain `list[str]`.
- **Not specifying checkpointer/HITL.** You'll get either a stray `InMemorySaver` or none at all — when you need exactly one.

## Minimal spec (for genuinely simple cases)

If the task is truly one line (a ReAct loop with 2-3 tools, no HITL, no structured output) — you can trim to 4 sections: goal / input-output / tools / provider. But **still spell out the state schema** — it's the most common pain point in generated code: the reducer for messages must be the function `add_messages` (not a string in Annotated), and append lists without a reducer (`operator.add`) are silently overwritten.

## Output check after generation

Once the codegen tool returns code, before showing it to the user:
1. Grep for the 10 pitfalls (a knowledge-retrieval tool like `search_agent_knowledge("pitfall annotated")` can remind you of the list; if RAG is unavailable — skip and use the §1 checklist from `/debug-langgraph-agent`).
2. Run the generated code through a Python check (that it at least parses and the imports are OK).
3. Run the acceptance criteria from section 9 of the spec.
4. If it doesn't work — move to `/debug-langgraph-agent`.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kirill-sviridov](https://github.com/kirill-sviridov)
- **Source:** [kirill-sviridov/agent-dev-skills](https://github.com/kirill-sviridov/agent-dev-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-kirill-sviridov-agent-dev-skills-agent-spec-writer
- Seller: https://agentstack.voostack.com/s/kirill-sviridov
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
