{
  "$type": "site.standard.document",
  "description": "I work with coding agents in two modes. For larger features, I write a detailed spec before any code. For smaller tasks, I skip the spec and set",
  "path": "/two-ways-to-direct-coding-agents/",
  "publishedAt": "2026-04-11T03:21:00.000Z",
  "site": "at://did:plc:bryys25pc2fnagnyxqgsglhd/site.standard.publication/3mn26bjkkmh23",
  "tags": [
    "AI",
    "Tools"
  ],
  "textContent": "I work with coding agents in two modes. For larger features, I write a detailed spec before any code. For smaller tasks, I skip the spec and set guardrails instead. Both work — they solve different problems.\n\nFULL SPEC\n\nFor new features or anything with non-obvious architectural decisions, I write everything out first — data flow, DB schema, API shape, edge cases. I have a spec skill that interviews me about all of this before any code gets written. What comes out is a document like:\n\n## Data Model\n- users table with email, hashed_password, created_at\n- sessions table with user_id, token, expires_at\n- No soft deletes — hard delete on account removal\n\n## API\n- POST /auth/register — validate, hash, insert, return session token\n- POST /auth/login — verify, create session, return token\n- Auth middleware checks session token on protected routes\n\n## Edge Cases\n- Duplicate email returns 409, not a generic error\n- Expired sessions return 401, frontend sends user to login\n\nThe agent follows this. It doesn't get to suggest alternatives or rethink things during execution. This eliminates drift — there's no room to wander.\n\nGUARDRAILS INSTEAD OF A SPEC\n\nFor smaller tasks — bug fixes, refactors, wiring up something that follows an existing pattern — I skip the full spec. I describe the problem and add constraints. A real prompt looks like:\n\nThe /auth/login endpoint returns 500 when the email doesn't exist.\nIt should return 401 with { error: \"invalid_credentials\" }.\n\nConstraints:\n- Do not modify the database schema\n- Do not change more than 20 lines\n- Keep changes in src/routes/auth.ts\n- Run the existing auth tests after fixing\n\nThe constraints keep the agent from over-engineering it. \"Do not modify the database schema\" prevents the agent from deciding it needs a login_attempts table. \"Keep changes in src/routes/auth.ts\" stops it from refactoring the error handling across three files.\n\nI couple these with validation — linting, type checks, tests — to catch anything that goes outside the boundaries.\n\nWHEN I USE WHICH\n\nNew system, multiple services, design decisions that affect the whole project? Full spec. A bug in a well-understood module, or a refactor that follows an existing pattern? Guardrails and go.\n\nThe gray area is medium-sized tasks — adding a feature to an existing system where the pattern is clear but there are a few decisions to make. I usually start with guardrails and tighten them if the agent drifts. If I find myself adding more than four or five constraints, that's a sign I should write a spec instead.",
  "title": "Two Ways to Direct Coding Agents"
}