DevSpeak is an AI platform that turns informal requirements into structured technical specifications for any language or framework, across a web app, a native macOS app, a VS Code extension, a CLI, and an MCP server. It works in three stages: Optimize, Translate, Refine. Context Projects ground output in project files and connectors under a closed-world rule. Missing details go to an Assumptions & Open Questions section. XML output is validated before delivery, automatic failover reroutes around provider outages, and every version is kept as an immutable snapshot.

How DevSpeak Works: An Architecture That Shows Its Gaps Instead of Guessing

The costly failure in AI-generated specifications is not a wrong answer. It is a confident answer written over a hole in the input: a file path that was never in the repository, a design decision nobody made, an empty response reported as success.

DevSpeak's output is not trustworthy because its models are smarter than anyone else's. It is trustworthy because every layer of the product is built to turn a gap into something visible, rather than letting a model fill the gap with a plausible guess. This post walks through those layers one at a time.

One Engine, Five Surfaces, No Assumed Stack

DevSpeak takes the way a person actually describes work ("we need the checkout to stop double-charging when people refresh") and returns a structured specification a developer or an AI coding agent can act on. That could be a technical spec, an RFC, a set of Jira tickets, an API design, a data model, or a prompt.

It ships on five surfaces, all backed by the same engine:

  • The web app at [the DevSpeak dashboard](/dashboard), where the Translation Editor lives.
  • A native macOS app, for people who would rather not keep a browser tab open.
  • A VS Code extension, published on both the VS Code Marketplace and Open VSX, which can include your open workspace as context.
  • A command-line tool, which writes documents to stdout so they pipe into the rest of your tooling.
  • An MCP server, available as a hosted endpoint and as an npm package, so any MCP-capable agent can call DevSpeak as a tool.
  • Because the engine is shared, a spec requested from the terminal follows the same contracts as one requested from the editor. The differences between surfaces are ergonomic, not semantic.

    The engine is also deliberately agnostic about technology. It recognises whatever languages and frameworks the evidence in front of it shows and writes in their idioms. When there is no evidence — no project, no attached files, no stack named in your request — it names no language, framework, database, or hosting platform at all. A specification that quietly assumes React and PostgreSQL because those are statistically common is the first kind of gap-filling this architecture refuses to do.

    Three Stages, Three Contracts That Never Overlap

    The core of the product is a pipeline of three stages. Only the middle one is required. What makes the pipeline reliable is less the stages themselves than the fact that each one has a narrow contract it is not allowed to exceed.

    Stage 1 — Optimize (optional). A monolingual copy-edit pass over your raw input. It fixes grammar, clarity, and tone, and it is not allowed to change meaning. In practice that means it keeps your grammatical subject and voice ("we need X" never becomes "X is required"), keeps the same sentences in the same order, keeps every name you mentioned, and stays close to your original length. It is deterministic: the same input gives the same output. And because its result replaces the text in your editor, it never answers a question or asks one. A question-shaped input comes back as better-written prose, not as a reply. If you dislike the edit, Undo restores what you typed.

    Stage 2 — Translate (required). The engine that turns input into a specification. Four controls calibrate the result:

  • Audience — Junior Dev, Senior Dev, Tech Lead, SRE, or Data Engineer. A junior developer needs the reasoning spelled out. An SRE needs failure modes, rollback, and observability. The same requirement produces genuinely different documents.
  • Context — Backend, Frontend, Mobile, Data/ML, or DevOps, which sets the concerns the spec prioritises.
  • Format — Technical Spec, Jira Tickets, API Design, RFC, Data Model, Prompt, or Optimize, which sets the document's structure.
  • Tone — a slider from concise to detailed that sets the density of the output, and, as the next sections show, how much of the engine's uncertainty it writes down.
  • The same four dimensions are exposed on the public API. A request is a small JSON body authenticated with the x-api-key header:

    ``bash

    curl -X POST https://www.devspeak.dev/api/v1/translate \

    -H "x-api-key: $DEVSPEAK_API_KEY" \

    -H "Content-Type: application/json" \

    -d '{

    "input": "Stop charging people twice when they refresh the checkout page.",

    "audience": "Senior Dev",

    "context": "Backend",

    "format": "Technical Spec",

    "tone": 80

    }'

    `

    API access is included on the Developer and Enterprise plans.

    Stage 3 — Refine (optional). Refinement works on the generated document, not on your original input. You send the previous output plus specific feedback ("split the migration into its own section", "the audience is on-call, cut the background"), and DevSpeak returns a complete, standalone replacement document rather than a patch. Your original input comes along only as reference, so a refinement can tighten the spec without drifting back toward the informal wording you started from. Iterative refinement is available on Vibecoder, Developer, and Enterprise.

    Separating the stages matters because each prevents a specific failure. A copy editor that is allowed to reinterpret will quietly change what you asked for. A translator that also rewrites your input makes it impossible to tell where your intent ended and the model's began. A refiner that starts over from the raw input throws away every correction you already made.

    The Closed World Is a Feature, Not a Limitation

    A specification about an existing codebase fails in a characteristic way. Everything visible in the context comes out correct, and everything invisible is invented: a helper module that sounds right, a configuration variable that follows the naming convention, a route the project never had. The invention reads exactly like the facts around it, which is what makes it dangerous.

    DevSpeak addresses this in three parts.

    Context Projects. A Context Project attaches persistent project instructions, uploaded documents and images, and a fixed set of retrieval connectors — GitHub, Web Search, and Context7 — to your translations, so you are not re-pasting the same background into every request. With a GitHub repository connected, DevSpeak ranks the repository's files against what you are asking about and reads the relevant source directly, instead of guessing from filenames. Context Projects are available on Vibecoder, Developer, and Enterprise. The [Context Project grounding tutorial](/tutorials/mcp/ground-translations-on-a-context-project) walks through the setup.

    The closed-world rule. When a translation runs against grounded context, anything not present in that context — a file, a route, a dependency, an environment variable, a symbol — is treated as not existing. That sounds restrictive. It is the opposite of restrictive for the person reading the spec, because it changes the model's default from "invent something plausible" to "say this is not there." A spec that says "no existing rate limiter was found; one must be introduced" is actionable. A spec that confidently extends a rate limiter that does not exist sends someone on a search that ends in confusion.

    Provenance, and the rule's own exception. Retrieval does not always succeed. A repository can be too large to read in full, a connector can time out, a page can refuse the fetch. DevSpeak reports this instead of hiding it: grounded output carries a Grounded or Partially grounded label, so you know how much of the project the engine actually saw. When a source is incomplete, the closed-world rule is suspended for that source, because "I did not see it" is no longer evidence that "it does not exist." The engine records an open question rather than asserting either way.

    Grounding is also fail-open. If a connector is unavailable, you still get a specification, just a less grounded one, and the label tells you so. The alternative, refusing to translate whenever any source hiccups, would train people to stop using grounding altogether.

    Uncertainty Goes in Quarantine, Not in the Spec

    Grounding covers what the engine can look up. A lot of what a specification needs cannot be looked up at all: the retention period nobody mentioned, whether the change must be backward compatible, who owns the rollback decision. A model under pressure to produce a complete-looking document will answer those questions itself, silently, in the body of the spec.

    At the detailed end of the tone slider, DevSpeak closes that path. Every output format ends with a mandatory Assumptions & Open Questions section, and every decision the input did not specify goes there instead of into the specification as though it were settled:

    `markdown

    Assumptions & Open Questions

  • Assumed: duplicate submissions are identified per checkout session, not per user.
  • Open: how long must an idempotency record be retained? The input does not say.
  • Open: should a detected duplicate return the original receipt or a 409?
  • `

    This is the most useful section of a DevSpeak document, and it is the one people read last. It is where you find the constraint you were holding in your head and never wrote down. A reviewer can answer an open question in thirty seconds. Nobody can review a decision that was made invisibly three paragraphs earlier.

    The tradeoff deserves stating plainly. At the concise end of the slider, the engine performs a tighter rewrite and does not add this section. Concise output is for when you already know the answers and want a compact document. If you are not sure you do, move the slider toward detailed.

    XML When the Reader Is a Machine

    Markdown is the right format when a person reads the output. When a program reads it — a prompt configuration, an agent definition, a data schema that feeds a build step — "mostly well-formed" is a bug.

    The Translation Editor on the web and in the macOS app lets you request deterministic XML instead of Markdown, and the public API accepts the same option through "responseFormat": "xml"`. XML responses are validated on the server before they are delivered. The root element is determined by the format you chose, so a Data Model and an API Design arrive with predictable, distinct roots. If a model's output strays from the expected structure, it is repaired or safely wrapped rather than handed to you malformed. The guarantee is simple: what arrives parses.

    The honest limit: well-formed is not the same as correct. Validation guarantees that your parser will not choke. It does not guarantee that every element says what you meant, which is what the Assumptions section and refinement are for.

    Failover That Does Not Go Dark

    A product that depends on a single model provider inherits that provider's outages as its own. DevSpeak's managed translation runs on a curated model stack spanning several providers. If the provider handling your request fails or stalls, the request fails over to another provider within the same request, and you get a specification instead of an error.

    Two details make the failover dependable rather than merely present.

    Time is budgeted across attempts. A slow first attempt is not allowed to consume the whole request window. Enough time is held back that another provider can still answer, which is the difference between real redundancy and a sequence of attempts that each time out in turn.

    Empty successes are treated as failures to prevent. Some reasoning-capable models spend their output budget on internal reasoning they never show you. When that budget runs out, the provider returns a technically successful response with nothing in it. DevSpeak disables that hidden reasoning wherever a provider requires it, so you do not get blank answers and you are not paying for tokens you never see. For the engineering detail behind this, see [Shipping a Provider-Agnostic LLM Gateway](/blog/shipping-a-provider-agnostic-llm-gateway).

    The tradeoff: when failover kicks in, a different model wrote your document than the one that usually does. If you want a specific model, pick it explicitly in the model picker. And if you would rather use a provider account you already pay for, every plan, Free included, lets you connect your own key.

    Every Version Is Kept, and None Is Overwritten

    A specification is rarely right on the first pass, and the second pass is not always better than the first. DevSpeak records every translation, every refinement, and every revert as an immutable snapshot in the document's history, with the model that produced it and whether it came from a translation, a refinement, or a revert.

    Reverting to an earlier version does not rewrite history either. It adds a new snapshot that restores the old content, so the record of what happened stays intact. You can audit how a spec evolved, compare versions, and go back to the draft before a refinement that overreached, without losing the refinement itself.

    One small design choice is worth mentioning because it shows the same principle again. If a refinement succeeds but saving it fails, DevSpeak still returns the refined document and tells you it was not saved. Silently dropping work you just waited for would be a hidden failure. Returning it with a warning is a visible one.

    What This Architecture Does Not Do

    The layers above reduce invented detail. They do not eliminate it, and this post would be misleading if it ended without saying so.

    Grounding is only as good as the context. The closed-world rule makes the engine honest about what it saw. It cannot make a Context Project contain what you forgot to connect.

    Concise mode trades transparency for brevity. Without the Assumptions & Open Questions section, unstated decisions are less visible. That is a choice you make with the slider, not one the engine makes for you.

    A specification is not a control. DevSpeak makes constraints explicit before anything runs. It is not a sandbox, a permission boundary, or a code review, and it is not a substitute for any of them.

    What the architecture does guarantee is narrower and, in practice, more valuable: when DevSpeak does not know something, the document says so in a place you will see it.

    Try It on a Requirement You Already Have

    The fastest way to understand the design is to watch it find a gap in your own writing. The Free plan requires no credit card. A 30-day Vibecoder trial, which adds iterative refinement, Context Projects, custom instructions, and document translation, also needs no payment method and returns to Free at the end without a charge.

    Paste a requirement you would normally hand straight to a teammate or an agent, set the tone to detailed, and read the Assumptions & Open Questions section first.

    Further Reading

  • [What Is DevSpeak? A Translation Layer Between Your Intent and Your AI Agent](/blog/what-is-devspeak)
  • [Your First Translation with DevSpeak](/tutorials/getting-started/your-first-translation)
  • [Every Control in the Translation Editor](/tutorials/translation-engine/translation-editor-controls)
  • [Ground MCP Translations on a Context Project](/tutorials/mcp/ground-translations-on-a-context-project)