Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Specs before code: field notes from a consultin...

Specs before code: field notes from a consulting team using Kiro

An agent can build a feature in an afternoon. Whether it's the feature you actually wanted is another question, and that's what this talk is about.

We start with Kiro, the agentic IDE built by a team inside AWS, and the three files it writes before any code: requirements.md (what we're building), design.md (how it will work) and tasks.md (the order we build it in).

Then ten principles our team picked up using Kiro on client work. For each one you get what it means in plain words, the config behind it and an example. Think steering files, hooks, permissions and review agents.

We finish with five things you can set up on Monday. Each takes about an hour, and none of them needs a budget line or anyone's permission.

Avatar for Nicolas DAVID

Nicolas DAVID

October 05, 2026

More Decks by Nicolas DAVID

Other Decks in Technology

Transcript

  1. AWS COMMUNITY DAY UAE / DUBAI / 3 OCTOBER 2026

    Specs before code Ten principles for working with agents, and how we set them up in Kiro Nicolas David Intuitive.ai Dubai, UAE – October 3rd, 2026
  2. WHO AM I ? Nicolas David VP Product & Solutions

    Engineering, EMEA & APAC, at Intuitive.ai Nicolas David leads Product & Solutions Engineering for EMEA and APAC at Intuitive.ai, an AWS Premier Partner, covering cloud migration, application and database modernisation, data platforms and platform engineering. He also contributes to IntuitiveIQ, Intuitive.ai's decision intelligence engine for enterprise AI. Before that, 11+ years at AWS: first as a technical trainer, then as lead on Bahrain's Cloud-First migration, 70+ government services moved, 57% cost reduction, 41% less downtime, presented at re:Invent. The country's two AWS Cloud Innovation Centers (University of Bahrain & Bahrain Polytechnic) started as his work as well. Outside the day job he organises the Bahrain, Dammam and Qatar AWS user groups. SPECS BEFORE CODE | NICOLAS DAVID
  3. BEFORE THE PRINCIPLES / FOUR MINUTES ON KIRO What Kiro

    is. And the three files that come before any code. SPECS BEFORE CODE | NICOLAS DAVID
  4. KIRO / WHAT IT IS An agentic development environment, built

    by a team inside AWS. One agent, several front ends. Surfaces IDE, CLI, web and mobile. Each one is a front end to the same agent, reading the same project config. Two modes Vibe sessions for quick, conversational changes. Spec sessions when a feature deserves a plan first. Around it Steering for standards, hooks for automation, MCP and Powers for tools. All of it lives in .kiro/ in the repo. The idea Write down what you mean before code exists, and keep it next to the code. SPECS BEFORE CODE | NICOLAS DAVID
  5. KIRO / A SPEC IS THREE FILES, IN ORDER Nothing

    gets built until all three exist and are approved. 01 WHA T 02 HO W 03 I N WHA T O R D E R requirements.md design.md tasks.md User stories Architecture and components Numbered steps, each building on the last EARS acceptance criteria: WHEN … SHALL … Numbered, so everything traces back → approve Data models and sequence diagrams Error handling and test strategy → approve Each linked to the requirements it serves Status updates as it runs Then the code, one task at a time. Requirements-first or design-first is chosen when the spec is created. SPECS BEFORE CODE | NICOLAS DAVID
  6. KIRO / 01 REQUIREMENTS.MD What we’re building, in sentences you

    can test ## Requirement 1: Pay for an order User story: As a customer, I want to pay for a pending order, so that it ships without a phone call. 1.1 WHEN a customer pays for an order in PENDING status THE SYSTEM SHALL record the amount, method and timestamp 1.2 WHEN the payment succeeds THE SYSTEM SHALL set the order status to CONFIRMED 1.3 WHEN the card is declined THE SYSTEM SHALL leave the order PENDING and record nothing EARS notation: a trigger, then a required behaviour. Each criterion is numbered, so the design, the tasks and the tests can all point back to it. SPECS BEFORE CODE | NICOLAS DAVID
  7. KIRO / 02 DESIGN.MD How it will work, decided before

    it’s built design.md payments-api ## Overview payments as a new module behind the orders API ## Architecture POST /payments/ -> PaymentService -> PaymentStore ## Sequence customer, API, service, store, order update (mermaid) ## Data models Payment(id, order_id, amount_cents, method, ts) ## Error handling declined: 402, order stays PENDING ## Testing property: a declined card never records a payment (1.3) (1.3) The expensive decisions live here: contracts, data shapes, failure modes. Cheap to change as text. Much less so once they’re code. SPECS BEFORE CODE | NICOLAS DAVID
  8. KIRO / 03 TASKS.MD The order we build it in,

    with every step traced back - [x] 1. Payment model and store - [x] 1.1 Payment model, amounts in integer cents - [x] 1.2 Store, with a unique index on order_id - _Requirements: 1.1_ - [ ] 2. POST /payments/ endpoint - _Requirements: 1.1, 1.3_ - [ ] 3. Confirm the order on success runs alongside 4 - _Requirements: 1.2_ - [ ] 4. Property test: a declined card records nothing - _Requirements: 1.3_ Each task builds on the one before and names the requirements it serves. Run all tasks works out which ones are independent and runs those side by side. SPECS BEFORE CODE | NICOLAS DAVID
  9. WHERE WE ARE GOING Ten principles for working with agents

    01 Write the intent, check the result 06 Throw the code away, keep the tests 02 Hand over whole features 07 Your name is on it 03 Put the context in the repo 08 Fence it in, then let it run 04 Let it check its own work 09 Start before the code 05 Spend your time on direction 10 Fix the setup, every time SPECS BEFORE CODE | NICOLAS DAVID
  10. PRINCIPLE 01 / 10 01 Write the intent. Check what

    comes back. SPECS BEFORE CODE | NICOLAS DAVID
  11. PRINCIPLE 01 / WHAT IT MEANS Most of the job

    is now saying what done looks like, then checking we got it. Intent The behaviour we want, the edge cases that matter, and how we will prove it. Written down before anything is generated. Review Targeted, and measured against that intent. Syntax is the agent’s problem now. Time The hours that used to go into typing go into the brief and the check. SPECS BEFORE CODE | NICOLAS DAVID
  12. PRINCIPLE 01 / HOW WE SET IT UP # when

    the intent changes 1 edit requirements.md, or ask Kiro to add the requirement 2 "Update design.md to reflect the new requirements" 3 tasks.md, then Sync Files new tasks map to the new requirements # when some of it already exists "Check which tasks are already complete" Kiro reads the codebase and ticks off what it finds The spec stays the source of truth after the first draft. Change the intent in the file, then let Kiro carry it down to the design and the tasks. SPECS BEFORE CODE | NICOLAS DAVID
  13. PRINCIPLE 01 / IN PRACTICE The same ask, written two

    ways WHA T G E T S T Y P E D “Add payments to the orders API.” WHA T D O N E L O O K S L I K E Who a signed-in customer, on their own orders only Which orders PENDING ones, and each one paid once Recorded amount, method, timestamp Afterwards the order moves to CONFIRMED Declined order stays PENDING, nothing recorded Proof a test that a second payment is refused The left one is what most tickets say. The right one is what the agent needs, and a spec drags it out of you even when you start from the left. SPECS BEFORE CODE | NICOLAS DAVID
  14. PRINCIPLE 02 / 10 02 Hand over whole features. Then

    go and do something else. SPECS BEFORE CODE | NICOLAS DAVID
  15. PRINCIPLE 02 / WHAT IT MEANS Give the agent a

    job big enough to run for half an hour, with its own finish line. The trap Prompt, wait a minute, test by hand, paste the error back, repeat. Nobody gets fast that way. Handover Build it, write the tests, run them, keep going until they pass. One instruction, and the agent is allowed to get it wrong on the way. In parallel Several agents on a steady queue, reviewed when we get to them. The limit is how many we can keep usefully busy. Next step Hours, then overnight, then agents starting agents. On client code we’re at the first step and we say so. SPECS BEFORE CODE | NICOLAS DAVID
  16. PRINCIPLE 02 / HOW WE SET IT UP $ kiro-cli

    --cloud > /repo our-org/orders-service > /spec new payments-api # the handover, one message Implement every task in the payments-api spec. After each task, run ruff check and pytest. Keep going until both pass. Stop only on a requirement conflict. A cloud session keeps working after the laptop shuts, and you can pick it up from the IDE, the browser or your phone. Run all tasks puts independent tasks into waves that run side by side. SPECS BEFORE CODE | NICOLAS DAVID
  17. PRINCIPLE 02 / IN PRACTICE What a handover looks like

    tasks.md payments-api [x] 1 Payment model and store R1.1 [x] 2 POST /payments/ endpoint R1.1 R1.2 [ ] 3 confirm the order on success wave 2 R2.1 [ ] 4 refuse a second payment on one order wave 2 R3.1 Tasks 3 and 4 don’t depend on each other, so they run together. Every task points back to a requirement, so “why does this exist?” has an answer in the file. SPECS BEFORE CODE | NICOLAS DAVID
  18. PRINCIPLE 03 / 10 03 Put the context in the

    repo. The agent starts from zero every time. SPECS BEFORE CODE | NICOLAS DAVID
  19. PRINCIPLE 03 / WHAT IT MEANS A new hire onboards

    once. An agent onboards every session, so the context has to be written down. Basics READMEs, architecture notes, tests that describe behaviour, clear module edges, types, builds that fail fast and say why. People benefit too. Agent context Steering for conventions, skills for procedures that load only when needed, setup scripts, CLI tools and MCP servers for what it can’t see. Legacy code Prepare one module at a time and point the agent at that module, never the whole repo. Memory Have it record design decisions and comment generously. The next session inherits the reasoning along with the code. SPECS BEFORE CODE | NICOLAS DAVID
  20. PRINCIPLE 03 / HOW WE SET IT UP .kiro/ .kiro/steering/api-design.md

    steering/ --- product.md what it’s for inclusion: fileMatch tech.md stack, commands fileMatchPattern: structure.md layout api-design.md api/ files only skills/ - "app/api/**/*.py" --Errors are problem+json. db-migration/SKILL.md Money is integer cents. The three foundation files load every time. api-design.md loads only when the agent touches a matching file. The skill loads only when a request matches its description. SPECS BEFORE CODE | NICOLAS DAVID
  21. PRINCIPLE 03 / IN PRACTICE The things we used to

    repeat in every chat .kiro/steering/tech.md - Python 3.12, FastAPI, Postgres. Tests: pytest -q - Money is integer cents. Never floats. - Migrations are generated, never hand-edited. - A new dependency needs a note in docs/decisions/. - Comment the why. The next session only has the file. A new engineer learns these once. An agent starts from nothing every session, so they go in a file, get reviewed like code, and are there for the next person too. SPECS BEFORE CODE | NICOLAS DAVID
  22. PRINCIPLE 04 / 10 04 Let it check its own

    work. Otherwise you’re the bottleneck. SPECS BEFORE CODE | NICOLAS DAVID
  23. PRINCIPLE 04 / WHAT IT MEANS If the agent can’t

    test and fix its work before we look, we are the slowest part of the loop. Same tools Every check we run on our own work, it should run too: linters, unit tests, a browser for UI, mocks of nearby services, the full stack on a laptop. Properties State the rule once and let it generate the cases nobody would write by hand. The trade Skip this and faster generation means more broken builds. Do it and quality goes up, because the agent runs the checks more consistently than we do. SPECS BEFORE CODE | NICOLAS DAVID
  24. PRINCIPLE 04 / HOW WE SET IT UP .kiro/hooks/lint-and-test.json #

    also on its list { pytest tests/properties -q "version": "v1", "hooks": [{ "name": "Lint and test on save", "trigger": "PostFileSave", docker compose up -d full stack, local mocks npx playwright test render and check the UI "matcher": "\\.py$", "action": { "type": "command", "command": "ruff check --fix && pytest -q" } }] } The hook fires on the agent’s own edits, so it sees its failures before we do. The right-hand list is what it can run without asking. SPECS BEFORE CODE | NICOLAS DAVID
  25. PRINCIPLE 04 / IN PRACTICE A rule, not a list

    of cases Property 3: an order is paid at most once validates R3.1 Falsifying example: test_single_payment( order=Order(status='PENDING', total=100), concurrent_attempts=2, ) AssertionError: 2 payments recorded for one order Nobody writes the test with two payments in flight at once. A property only needs the rule. It finds the case, then shrinks it to the smallest one that still breaks. SPECS BEFORE CODE | NICOLAS DAVID
  26. PRINCIPLE 05 / 10 05 Spend your time on direction.

    The typing is the cheap part now. SPECS BEFORE CODE | NICOLAS DAVID
  27. PRINCIPLE 05 / WHAT IT MEANS Code is cheap to

    change now. Contracts, dependencies and architecture still cost what they always did. Design partner Let the agent research options and pick holes in the plan before anything gets built. Evidence Two plausible designs? Have both prototyped and compare them. A debate that took a meeting now takes an afternoon. Spec first Once the direction is set, write the spec with the agent. Leave it vague and the agent makes the tradeoffs for you, and unpicking them costs more than the spec. Attention Will it hold under real load, do the tradeoffs still stand, is it ready for users. SPECS BEFORE CODE | NICOLAS DAVID
  28. PRINCIPLE 05 / HOW WE SET IT UP # three

    choices before any code exists Workflow Mode Then requirements-first behaviour is clear, architecture is open design-first architecture fixed, or feasibility unclear standard we approve requirements, design, tasks quick spec all three in one go, for features we know well Analyze Requirements before design, every time The workflow is fixed once the spec exists, so pick it on purpose. Analyze Requirements takes minutes, because it reasons across all the requirements at once. SPECS BEFORE CODE | NICOLAS DAVID
  29. PRINCIPLE 05 / IN PRACTICE Two designs, settled by evidence

    # one message, two branches Prototype both designs, one branch each: A idempotency key in a header, stored with the payment B unique constraint on payments.order_id Run the same property tests against both. Report which fails, and what each costs in migrations and API changes. Then update design.md with the choice. An afternoon of agent time instead of a design review that goes in circles. The decision and the reason end up in design.md, where the next person will find them. SPECS BEFORE CODE | NICOLAS DAVID
  30. PRINCIPLE 06 / 10 06 Throw the code away. Keep

    the tests. SPECS BEFORE CODE | NICOLAS DAVID
  31. PRINCIPLE 06 / WHAT IT MEANS Code is cheap to

    write again. Keep asking whether it’s worth shipping, and worth running for years after. Old reasons Throwing code away used to hurt because it took months and felt personal. Neither holds any more. Sunk cost Prototype for a day and walk away. Get close to done in two weeks, then start over if it’s the wrong product. What stays Tests at the boundary: end to end for behaviour, properties for invariants, load for concurrency at scale. Unit tests go in the bin with their code. SPECS BEFORE CODE | NICOLAS DAVID
  32. PRINCIPLE 06 / HOW WE SET IT UP tests/ workspace

    permissions.yaml contract/ survives rewrites rules: e2e/ checkout flow properties/ paid at most once match: ["./tests/contract/**"] load/ parallel checkouts effect: ask unit/ - capability: fs_write goes with its code An agent told to get to green will happily edit the test. Making contract changes an ask keeps that call with a person. SPECS BEFORE CODE | NICOLAS DAVID
  33. PRINCIPLE 06 / IN PRACTICE The contract any rewrite has

    to satisfy WHEN a payment is confirmed for an order, THE SYSTEM SHALL record exactly one payment for that order, however many requests arrive at the same time. True of this Python service today, and of whatever replaces it. It can be written before anyone picks the stack, and it’s the acceptance test for whichever one wins. SPECS BEFORE CODE | NICOLAS DAVID
  34. PRINCIPLE 07 / 10 07 Your name is on it.

    Whoever typed it. SPECS BEFORE CODE | NICOLAS DAVID
  35. PRINCIPLE 07 / WHAT IT MEANS What ships under our

    name is ours, whoever or whatever wrote it. Speed without quality is risk arriving sooner. Early on Read agent output line by line. That’s how we learn where the model is good and where it slips. AI reviewer Takes the first passes on correctness, security, maintainability, test quality and known bug patterns. Locally before the PR, again in CI. Our attention Design, what the change does upstream and downstream, and whether the security boundaries hold. After merge Let the agent watch the deploy and start on a fix if something regresses. Ownership ends in production. SPECS BEFORE CODE | NICOLAS DAVID
  36. PRINCIPLE 07 / HOW WE SET IT UP .kiro/agents/pr-review.json {

    "name": "pr-review", "description": "Reviews changes before a pull request", "prompt": "Check the diff against the spec and the steering files.", "tools": ["read", "shell"], "permissions": { "rules": [ { "capability": "shell", "match": ["git diff *", "pytest *"], "effect": "allow" }, { "capability": "fs_write", "match": ["**"], "effect": "deny" } ]} } # in CI, on every pull request kiro-cli chat --no-interactive --agent pr-review "Review the diff against main" Read-only by construction: it can diff and run tests, and it can’t write a file. Same agent on a laptop before the PR and headless in CI. SPECS BEFORE CODE | NICOLAS DAVID
  37. PRINCIPLE 07 / IN PRACTICE Pin what you promised not

    to break bugfix.md duplicate-payment-on-timeout Current WHEN a card payment times out and is retried, THE SYSTEM records it twice Expected WHEN a card payment times out and is retried, THE SYSTEM SHALL record it once Unchanged WHEN a payment succeeds first time, THE SYSTEM SHALL CONTINUE TO confirm the order A bugfix spec writes down the behaviour that must not change and generates a test for it, alongside the test for the fix. The usual failure is the third change quietly undoing the first. SPECS BEFORE CODE | NICOLAS DAVID
  38. PRINCIPLE 08 / 10 08 Fence it in. Then let

    it run. SPECS BEFORE CODE | NICOLAS DAVID
  39. PRINCIPLE 08 / WHAT IT MEANS Limit what the agent

    can reach, then stop watching it. Approving every tool call isn’t oversight. Scope Files, tools, network and credentials: only what the task needs. Widening Start narrow and open up as the limits prove themselves, until the only thing still gated is what can’t be undone. Production No production account or deploy credentials unless someone granted them on purpose. Automated checks Static security testing, credential scanning, and automated reasoning that checks output against intent. SPECS BEFORE CODE | NICOLAS DAVID
  40. PRINCIPLE 08 / HOW WE SET IT UP ~/.kiro/settings/permissions.yaml rules:

    # never, or ask first - capability: fs_read - capability: fs_write match: ["./src/**", "./tests/**"] effect: allow - capability: shell match: ["pytest *", "ruff *", "git diff *"] match: ["**/*.env", "**/*.pem"] effect: deny - capability: shell match: ["aws *", "git push *"] effect: ask effect: allow Deny beats allow at every scope. Workspace rules live outside the repo, so a cloned repo can’t grant itself anything. Kiro always asks before touching .git or hooks, and the agent can never write its own settings. SPECS BEFORE CODE | NICOLAS DAVID
  41. PRINCIPLE 08 / IN PRACTICE How the Kiro team fenced

    its own on-call agent 96.9% of its tool calls are reads. The rest can be gated. Default ReadOnly through a role allowlist. Asking for Admin returns an error. Credentials Minted per session, scoped to the task the agent declared. Humans only Resolving a ticket, or changing its severity. Cost Capped by structure: timeouts, stuck detection, a concurrency cap. Their numbers, from the Kiro team’s write-up on trusting an agent with production incident triage. Not ours. SPECS BEFORE CODE | NICOLAS DAVID
  42. PRINCIPLE 09 / 10 09 Start before the code. The

    reading is half the job. SPECS BEFORE CODE | NICOLAS DAVID
  43. PRINCIPLE 09 / WHAT IT MEANS Once the habits work

    for code, use them for everything around it. Same pattern Give it context, say what done looks like, let it draft, then review before anyone else sees it. Where Design docs, requirement reviews, status updates, sprint summaries, on-call reports, documentation. Whole lifecycle Planning, build, test, deploy, operate. Each agent gets clear intent, fast feedback and fenced access. Shared setup Pipeline, on-call and docs agents read the same steering and use the same tools, so they behave alike. SPECS BEFORE CODE | NICOLAS DAVID
  44. PRINCIPLE 09 / HOW WE SET IT UP ~/.kiro/steering/ house-style.md

    .kiro/skills/uat-pack/SKILL.md every repo .kiro/steering/ structure.md name: uat-pack this repo .kiro/agents/ pipeline oncall --description: Turn an approved requirements.md into a UAT docs script and a one-page change note. Use when a spec is # same steering, same tools approved. --- Global steering applies everywhere, and the workspace wins on a conflict. A skill loads only when a request matches its description. The Kiro team runs 107 on-call playbooks that way, with just an index in context. SPECS BEFORE CODE | NICOLAS DAVID
  45. PRINCIPLE 09 / IN PRACTICE The step that writes no

    code at all 01 Logical inconsistencies 02 Ambiguity 03 Conflicting constraints 04 Unstated assumptions 05 Missing edge cases Analyze Requirements takes minutes, because it reasons across the requirements instead of inside one. Run it before design, every time. SPECS BEFORE CODE | NICOLAS DAVID
  46. PRINCIPLE 10 / 10 10 Fix the setup, every time.

    Each wrong turn is a missing file. SPECS BEFORE CODE | NICOLAS DAVID
  47. PRINCIPLE 10 / WHAT IT MEANS Every wrong turn and

    every needless interruption asks the same thing: what stops this happening again? The fix A steering rule, a skill for the procedure it got wrong, a CLI tool for the manual step, an MCP server for missing context, or wider access. Compounding Agents move from waiting for prompts to working in the background on bugs and tech debt. New models When one ships, re-check the workarounds built for the old one. Some can go. Two products The one the client pays for, and the one that builds it. SPECS BEFORE CODE | NICOLAS DAVID
  48. PRINCIPLE 10 / HOW WE SET IT UP .kiro/steering/tech.md -

    Migrations are generated, never hand-edited. + - After any change under app/models/, generate the + migration and run it locally before the tests. + - Never edit a migration that is already merged. # new model? re-read this file, delete what it no longer needs The usual wrong turn: a model changes and the migration doesn’t. Three lines, reviewed like code, and every later session starts with them. SPECS BEFORE CODE | NICOLAS DAVID
  49. PRINCIPLE 10 / IN PRACTICE Same team, same agent: what

    they kept fixing Lessons A correction is stored once and fed into later sessions. The agent also patches the doc that misled it. One stale line A wrong sentence in a reference doc spread into several tickets before anyone caught it. They fixed the doc, then asked what else it misled. Bad memory Interrupted sessions once saved raw ticket comments as lessons. Schema checks before writing and a nightly prune fixed it. New playbooks After a new kind of incident the agent drafts the playbook, and engineers review it like code. From the Kiro team’s incident triage write-up. SPECS BEFORE CODE | NICOLAS DAVID
  50. WHERE TO START, AND THE ORDER IS THE POINT 01

    One tech.md, written by whoever complains most in code review. 02 One feature specced end to end, read out loud to whoever asked for it. 03 One invariant turned into a property test, on the thing that would hurt. 04 One hook, for the rule you are tired of repeating. 05 Then a shared steering repo, a review agent, and CI. About an hour each. None of them needs a budget line or anybody’s permission. SPECS BEFORE CODE | NICOLAS DAVID