Skip to content

Walkthrough: Building an Online Chess Game with Weftra ​

This walkthrough takes one small project from an almost-empty repository to a working chess game, built by Weftra. You will:

  1. Create a repository with a single README.
  2. Enroll it in Weftra, letting Weftra survey the repository first.
  3. Describe the game and let Weftra write the spec, ask you questions and build it.
  4. Watch the run, review the branch, the draft pull request and the signed Evidence Pack.
  5. Iterate: fold in review comments, and build the next feature on top of unmerged work.

Every step shows the ways you can do it. Pick the one that fits how you work, or mix them.

Way to drive WeftraWhat it isCredential
DashboardThe web UI at http://localhost:3100An admin, approver or user account (the dashboard does not accept a project key)
APIcurl against the same routes the dashboard usesThe project key (fa_...). The admin key only where a route needs it
In an IDEClaude Code in VS Code or Cursor, talking to Weftra over MCPThe project key, read from your environment
In an agent consoleThe Claude Code CLI over MCP, or claude.ai and ChatGPT as remote connectorsThe project key, or an OAuth sign-in for claude.ai and ChatGPT

The two MCP modes get the same tools. They can draft specs, submit and track features, and answer Weftra's questions. They cannot create projects, change settings, approve work or open pull requests. Each step says when a mode can't do something, and why.


Before you start ​

You need these for every mode:

  • A running Weftra instance. Follow the 10-minute quickstart through step 4: install, .env, the sandbox image (docker build -t fa-runtime:latest containers/fa-runtime) and npm run build && npm start.
  • A GitHub account, an SSH key on the Weftra host with push access to the repository you will create, and optionally a personal access token in GITHUB_TOKEN so Weftra can open draft pull requests. The quickstart's Prerequisites list the token's scopes.
  • The admin key (ADMIN_API_KEY in .env). You need it once, to enroll the project.

Then, for the mode you want:

ModeAlso needsWhere to set it up
DashboardA browserNothing more
APIcurl and jqNothing more
In an IDEClaude Code installed in VS Code or CursorClaude Code docs, then "Claude Code" in Drive Weftra from your assistant
Claude Code CLIClaude Code installedClaude Code docs, then "Claude Code" in Drive Weftra from your assistant
claude.ai or ChatGPTWeftra on a public HTTPS address, with MCP over HTTP and OAuth turned on"Put Weftra on the internet with Cloudflare Tunnel and Access" in SETUP.md, then the claude.ai or ChatGPT section of Drive Weftra from your assistant
The fa CLI (optional)A built Weftra checkout"A terminal or coding agent" in Drive Weftra from your assistant

Only claude.ai and ChatGPT need a public address. They connect from their own servers. Everything else on this page talks to Weftra over loopback.


Step 1: Create the chess game repository ​

Create a new repository and give it one commit. This matters: a brand-new, empty GitHub repository has no main branch yet, and a feature run against it currently fails at checkout.

bash
# With the GitHub CLI
gh repo create my-chess-game --public --clone
cd my-chess-game

# Or create it on github.com and clone it
git clone git@github.com:YOUR_USERNAME/my-chess-game.git
cd my-chess-game

Add a README and push it:

bash
echo "# My Chess Game" > README.md
git add README.md
git commit -m "Initial commit"
git push -u origin main

On github.com you can tick Add a README when you create the repository instead. Either way, main now exists and Weftra will build everything else.

Note the repository's SSH URL, git@github.com:YOUR_USERNAME/my-chess-game.git. Weftra only accepts the SSH form and clones with the host's SSH key.


Step 2: Start Weftra ​

If it isn't running yet:

bash
cd /path/to/weftra
npm run build && npm start

You should see:

[weftra] API server running on 127.0.0.1:3100

Weftra listens on loopback only. The dashboard is at http://localhost:3100, and the API reference at http://localhost:3100/api-docs.

For the API examples below, set:

bash
export WEFTRA=http://localhost:3100
export ADMIN_API_KEY=...        # the value in Weftra's .env

Step 3: Enroll the project ​

Enrolling creates the project and gives you its project key, the credential every later step uses. It is an admin action. A project key cannot create projects, because there is no project yet to scope it to.

Before you enroll, let Weftra survey the repository. It makes a shallow clone into a throwaway workspace, reads the files that describe how the project builds (CI workflows, package manifests, Makefile, Dockerfile, README, CONTRIBUTING, AGENTS.md, CLAUDE.md) and proposes the configuration. It runs nothing from the repository. Each proposed command cites the file and line it came from, and Weftra checks that the line really says that before showing it. The survey ends with a readiness verdict (ready, ready_with_findings or not_ready), with each finding and how to fix it.

For a repository that only holds a README, expect findings such as no CI and no test command to find. That's fine here. The first feature will add the tests, and you'll declare the test command afterwards (Step 9).

In the dashboard ​

  1. Open http://localhost:3100, paste the admin key into the login box and click Sign In with API Key.

  2. On the Projects tab, click + Enroll Project.

  3. Fill in Project Name (my-chess-game) and Repository URL (the SSH URL), then click Survey repository. The form locks while the survey runs and shows its progress. In a minute or so it fills in the default branch, runtime image and any commands it found, and shows the readiness verdict.

  4. Set Autonomy Mode to Auto + Safety (auto_safe). Step 4 explains why.

  5. Tick Auto-create Draft PRs if you set GITHUB_TOKEN.

  6. Click Save.

  7. Weftra shows the project key once, in a pop-up. Copy it now:

    bash
    export PROJECT_API_KEY=fa_...

    This is the only time the full key is shown. There is no route that shows it again.

Optional: click Check on the project's row, then Run Check. Weftra runs the project's declared setup, test and verify commands in the sandbox without building anything, so you know the environment works before an agent depends on it. With only a README there is little to check yet; it is more useful after Step 9.

With the API ​

Start the survey (admin key):

bash
curl -s -X POST "$WEFTRA/api/projects/propose" \
  -H "Authorization: Bearer $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"repo_url": "git@github.com:YOUR_USERNAME/my-chess-game.git"}'

repo_url is the only field it accepts. It answers 202 straight away with a survey_id and a report_url. Poll the report until status is done:

bash
curl -s "$WEFTRA/api/projects/propose/<survey id>" \
  -H "Authorization: Bearer $ADMIN_API_KEY" | jq '{status, phase, proposal, readiness}'

The survey never creates the project. Read the proposal, then enroll:

bash
curl -s -X POST "$WEFTRA/api/projects" \
  -H "Authorization: Bearer $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "my-chess-game",
    "repo_url": "git@github.com:YOUR_USERNAME/my-chess-game.git",
    "default_branch": "main",
    "tech_stack": ["html", "css", "javascript"],
    "autonomy_mode": "auto_safe",
    "auto_create_pr": true
  }' | jq '{id, name, autonomy_mode, api_key}'

auto_create_pr is off unless you set it. Leave it out if you have no GITHUB_TOKEN. Save the api_key and the project id; the key is returned in full only this once:

bash
export PROJECT_API_KEY=fa_...
export PROJECT_ID=...

In an IDE or agent console ​

Not with a project key. The MCP tools a project key gets have no way to create a project, because creating one is an admin action. Enroll in the dashboard or with the API, then come back with the project key.

There is one opt-in exception for admins. If the operator sets both FA_MCP_HTTP_ENABLED=true and FA_MCP_USER_SESSIONS_ENABLED=true, a named admin user can connect an MCP client to /api/mcp with their own user key. That session has three tools, create_project, issue_project_key and list_own_projects. create_project does not run the survey, and it accepts only po_approval (the default) or auto_safe as the autonomy mode. issue_project_key replaces a project's API key, the same act as the dashboard's "Re-issue API key" button or POST /api/projects/:id/regenerate-key. The same session is also reachable over the local stdio server via FA_USER_API_KEY, independently of that flag. See "Creating a project from an MCP client" in the User Guide.


Step 4: Decide how much Weftra asks you ​

Two choices decide whether Weftra writes the spec and asks you questions, or builds straight from what you send.

The project's autonomy mode (an admin sets it):

ModeDashboard labelWhat happens to a new featureWho answers Weftra's questions
full_autoFull AutoGoes straight to the queue. No analysis, so no questionsNobody is asked
auto_safeAuto + SafetyWeftra analyzes it first and may ask questions. The feature waits in clarification_needed until they're answeredYou
po_approvalPO Approval RequiredWaits in awaiting_approval for an approver, then is analyzed like auto_safeYou
full_auto_analyzeFull Auto + Unattended Analyze (experimental)Analyzed, and a sandboxed answerer replies for youAn automatic answerer

This walkthrough uses auto_safe, so you see the question-and-answer loop.

What you send with the feature:

You sendWhat Weftra does
A short description of what you wantWeftra writes the spec itself, at spec_path if you give one, otherwise docs/features/<slug>.md
A finished spec in spec_content (with spec_path)Weftra commits it to the branch byte for byte and never rewrites it

Two project settings make the loop stricter. Both are on the project form, under the same names:

  • Force clarify (force_clarify). Analysis must ask at least one real question on its first pass, even when the request looks clear. Admin-only: a project key that sends it gets 403.
  • Require spec approval (require_spec_approval). When Weftra wrote the spec (you sent no spec_content), the run pauses in awaiting_spec_approval before any code is written. An admin or approver reads the spec in the feature view, edits it if needed, and clicks Approve Spec or Reject Spec. The person who submitted the feature cannot approve it. An admin usually sets this. The project key can also switch it on or off for its own project, but it can never approve.

The details are in Autonomy Modes and "Clarifying Q&A" in the User Guide.


Step 5: Connect your IDE or agent console ​

Skip this step if you'll use only the dashboard and the API.

Every MCP client acts as the one project whose key it holds. Keep the key out of the repository and out of command lines:

bash
export FA_PROJECT_API_KEY="$PROJECT_API_KEY"   # in your shell profile or a secrets manager

Claude Code in VS Code or Cursor, and the Claude Code CLI ​

Claude Code reads a project-level .mcp.json. The CLI and the editor extension use the same file. Add it to the root of my-chess-game:

json
{
  "mcpServers": {
    "weftra": {
      "command": "npm",
      "args": ["run", "--silent", "mcp-server", "--prefix", "/path/to/weftra"],
      "env": {
        "FA_BASE_URL": "http://127.0.0.1:3100",
        "FA_PROJECT_API_KEY": "${FA_PROJECT_API_KEY}"
      }
    }
  }
}

/path/to/weftra is your Weftra checkout. ${FA_PROJECT_API_KEY} is read from your environment, so the file is safe to commit.

  • CLI: run claude in the repository, approve the weftra server when asked, and run /mcp to check that it's connected.
  • VS Code or Cursor: open the repository, start Claude Code from the editor, approve the weftra server, and check it with /mcp. Start the editor from a shell where FA_PROJECT_API_KEY is set, so the server can read it.

If the operator has turned on MCP over HTTP (FA_MCP_HTTP_ENABLED=true), you can point the same file at /api/mcp instead of a local checkout. "Claude Code" in Drive Weftra from your assistant has that variant.

claude.ai and ChatGPT ​

These connect from Anthropic's and OpenAI's servers, so the operator first puts Weftra on a public HTTPS address and turns on the HTTP endpoint and OAuth sign-in:

env
FA_MCP_HTTP_ENABLED=true
FA_MCP_OAUTH_ENABLED=true
FA_MCP_OAUTH_REDIRECT_ALLOWLIST=https://claude.ai/api/mcp/auth_callback,https://chatgpt.com/connector_platform_oauth_redirect
APP_BASE_URL=https://weftra.example.com

Then you add a custom connector with the URL https://weftra.example.com/api/mcp, click Connect, sign in to Weftra as an admin, pick my-chess-game as the one project the connector may act for, check that the destination is the assistant's callback, and approve. No key is pasted. The full steps, and what to check on the consent page, are in Drive Weftra from your assistant.

The tools you'll use ​

ToolWhat it does
draft_spec, clarify_spec, refine_spec, estimate_specWeftra's Builder: draft a spec from plain English, ask questions before anything is submitted, revise a draft, estimate its cost and scope
submit_featureSubmit the feature
get_feature_status, list_featuresRead a feature's status, branch and PR link
await_featureWait until the feature reaches a state that needs you (by default implemented, merged, wont_merge, failed, cancelled, clarification_needed, awaiting_credits or awaiting_auth)
get_clarifications, answer_clarificationRead Weftra's open questions and answer them
list_projectsShow which project the connection acts for

Step 6: Draft and submit the first feature ​

The first feature builds the whole first version of the game. Here is the intent you'll hand to Weftra:

Build a single-page chess game that runs in the browser with no server beyond static files. Render an 8x8 board with the standard pieces. Enforce the full rules: legal moves for every piece, turns, captures, check, checkmate, stalemate, castling, en passant and promotion (to a queen is fine). Click a piece to select it, highlight its legal moves, click a square to move. Show whose turn it is, the game status and a move history in algebraic notation, with a New Game button. Dark theme, works on desktop and tablet. Use index.html, css/style.css, js/chess.js (rules), js/ui.js (rendering) and js/app.js. Add a package.json whose npm start serves the files and whose npm test runs unit tests for the chess rules.

You don't have to turn that into a spec yourself. With a short description, Weftra writes the spec, and in auto_safe it can ask you about anything unclear.

In the dashboard ​

Draft it with the Builder first (optional). Open the Builder tab and pick the project. Paste the intent, click Ask clarifying questions and answer them, then click Draft spec. Edit the draft (title, description, acceptance criteria, scope boundaries and the rest), use Refine to ask for changes in plain English, and read the estimate. When it looks right, click Submit as feature.

Or submit directly. On the Features tab, click + Submit Feature, choose the project, enter a Title and the intent as the Description, and click Submit.

With the API ​

Submit a short description with the project key:

bash
curl -s -X POST "$WEFTRA/api/features" \
  -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "title": "Build the first version of the chess game",
    "priority": "high",
    "description": "Build a single-page chess game that runs in the browser ... (the intent above)"
  }' | jq '{id, status}'

Only title and description are required. priority is low, medium (the default), high or critical. Save the id:

bash
export FEATURE_ID=...

With auto_safe, the status starts in pending and moves to analyzing.

If you already have a finished spec, send it as spec_content with the path to commit it at. Weftra writes it to the branch exactly as sent and skips writing its own:

bash
jq -n --rawfile spec chess-v1-spec.md '{
  title: "Build the first version of the chess game",
  description: "Implement the spec of record at specs/chess-v1/spec.md.",
  spec_path: "specs/chess-v1/spec.md",
  spec_content: $spec
}' | curl -s -X POST "$WEFTRA/api/features" \
  -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
  -d @- | jq '{id, status}'

The Builder is on the API too, with the project key: POST /api/builder/clarify, /api/builder/draft, /api/builder/refine, /api/builder/estimate and /api/builder/submit. The fa CLI wraps submission as fa submit --title ... --description ... (add --spec <path> to send a file as spec_content).

In an IDE or agent console ​

Ask your assistant in plain English. For example, in Claude Code in VS Code, Cursor or the terminal, or in a claude.ai or ChatGPT chat with the Weftra connector on:

Use Weftra to build the first version of a chess game in this project. Here is what I want: (paste the intent). Use clarify_spec and relay Weftra's questions to me, then draft_spec, show me the draft and the estimate_spec result, and apply any changes I ask for with refine_spec. When I say go, submit it with submit_feature as a short description of the intent. Don't write the spec or answer open questions yourself. Then wait for it with await_feature.

Two things in that prompt matter. "Short description" keeps the assistant from sending a finished spec, so Weftra writes the spec and gets to ask its questions. "Relay Weftra's questions to me" keeps the assistant from answering them itself.

The Builder tools make model calls on the operator's credential, so they are rate-limited per project. If a tool refuses with a rate limit, wait a minute and try again. Nothing is created until submit_feature.


Step 7: Answer Weftra's questions ​

In auto_safe, Weftra analyzes the feature. If something is unclear (two-player only or against the computer? which test framework?), it asks, and the feature waits in clarification_needed. The build starts once every question is answered. If analysis has no questions, the feature goes straight to queued and you can skip this step.

In the dashboard ​

Open the feature from the Features tab. Each open question has an answer box and a Submit Answer button.

With the API ​

Read the open questions from the feature record:

bash
curl -s "$WEFTRA/api/features/$FEATURE_ID" \
  -H "Authorization: Bearer $PROJECT_API_KEY" \
  | jq '{status, clarifications: [.clarifications[] | select(.status == "pending") | {id, question}]}'

Answer each one:

bash
curl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/clarifications/<clarification id>/answer" \
  -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
  -d '{"answer": "Two players on one device for now. Use vitest for the tests."}'

In an IDE or agent console ​

If you used the prompt above, this happens in the conversation. await_feature returns clarification_needed, the assistant calls get_clarifications and shows you the questions, and answer_clarification sends your answers back. Then it calls await_feature again.

A question that comes from a recorded earlier decision is for an admin or approver to answer. The project key gets 403 on it, over MCP and the API alike. Answer it in the dashboard.


Step 8: Watch the run ​

The agent loop checks for queued work every 30 seconds by default (AGENT_POLL_INTERVAL_MS). The feature moves queued → in_progress → implemented. The run happens in a sandbox container, never on your host: Weftra clones the repository, branches, has the agent build the game, runs the tests, writes the docs, commits, pushes the branch and opens the draft PR.

In the dashboard ​

  • The Active Runs panel on the Overview tab lists every live run.
  • In the feature list, click Logs on the running feature, or open the feature and click View live logs. Both open the live log page, /logs.html?id=<feature id>.

With the API ​

bash
curl -s "$WEFTRA/api/features/$FEATURE_ID" \
  -H "Authorization: Bearer $PROJECT_API_KEY" | jq '{status, branch_name, pr_url}'

The live log itself is a dashboard page. Its API route needs an admin or user credential, not a project key.

In an IDE or agent console ​

await_feature waits up to 60 seconds per call by default (the server caps how long), and returns { timed_out: true, ... } when nothing has changed yet, so the assistant calls it again. get_feature_status gives the current status at any time. MCP has no live-log tool; open the dashboard's log page if you want to watch the agent work.


Step 9: Review the result ​

When the status is implemented, the feature record has a branch_name and, if you set GITHUB_TOKEN and auto_create_pr, a pr_url for a draft pull request. Weftra never merges it. That's your call.

Try the branch ​

bash
cd my-chess-game
git fetch origin
git checkout <branch name>      # the feature's branch_name, feature/<slug>-<id>
npm install
npm test
npm start

You should get a playable board with move highlighting, a status line and a move history, plus the spec Weftra wrote (under docs/features/, or at the spec_path you gave) and tests for the chess rules.

Turn on the test gate ​

Weftra runs the project's declared test_command itself after the agent finishes. Only that run counts as evidence, not the agent's own claim that tests passed. The README-only repository had no test command, so this first run's test gate could only warn. Now that the game has tests, declare the command. The project key can do this for its own project:

bash
curl -s -X PATCH "$WEFTRA/api/project" \
  -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
  -d '{"test_command": "npm ci && npm test"}'

In the dashboard, an admin sets Test command on the project form (Edit on the project's row). From now on a feature whose tests fail is not shipped. MCP has no settings tools, so do this in the dashboard or with the API.

The draft PR ​

The draft PR carries the feature request, its description, the test results and a documentation section pointing at the spec.

No PR? If the token was missing or expired when the run finished, open the PR now. In the dashboard, open the feature and click Create PR. With the API:

bash
curl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/create-pr" \
  -H "Authorization: Bearer $PROJECT_API_KEY" | jq '{pr_url}'

If an open PR for the branch already exists, Weftra records that one instead of opening a second. There is no MCP tool for this.


Step 10: Review the Evidence Pack ​

Every feature has an Evidence Pack: one signed statement of what happened to it. It binds the head commit to the spec's hash, the approvals, the reviewer and security verdicts, the test and verify gate results, the sandbox the run used, the cost and the position in the run ledger. Every field is read from Weftra's own records. Nothing in it comes from a request. It is how you, or someone you hand it to, can check the change after the fact.

From the dashboard ​

Sign in to the dashboard at http://localhost:3100 (your ADMIN_API_KEY works as the login key), open the feature, and open the collapsed Evidence section — it reads the pack only once you open it. From there:

  • Verify signature checks the held pack against this instance's published key, and shows the key id and whether newer ledger events exist since this pack was read.
  • Download JSON saves the signed envelope.

Any approval you made signed in with ADMIN_API_KEY this way shows that approval's separation of duties as not_asserted in the pack, not satisfied — the shared admin key proves a role, not a named person, and the pack only reports separation as satisfied for a verified named approver.

MCP has no Evidence Pack tool, so the dashboard and the API below are the two ways to reach one.

Read it from the API ​

As JSON (the signed envelope, { statement, signature, key_id, packed_at }):

bash
curl -s "$WEFTRA/api/features/$FEATURE_ID/evidence-pack" \
  -H "Authorization: Bearer $PROJECT_API_KEY" > pack.json
jq '.statement | {spec, approvals, verdicts, gates, containment, cost, ledger}' pack.json

As a page you can read:

bash
curl -s "$WEFTRA/api/features/$FEATURE_ID/evidence-pack?format=markdown" \
  -H "Authorization: Bearer $PROJECT_API_KEY"

A project key reads only its own project's packs. An approver reads the packs of linked projects, and an admin reads any. The cost covers the implementation run only, not review passes.

Verify it ​

Check that the signature you hold matches the statement you hold:

bash
jq '{statement, signature, key_id}' pack.json | curl -s -X POST \
  "$WEFTRA/api/features/$FEATURE_ID/evidence-pack/verify" \
  -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
  -d @- | jq

The answer is { valid, reason, key_known, current_last_seq }. The pack changes as new verdicts land, so an older copy is not a forgery. Compare current_last_seq with your copy's statement.ledger.last_seq to see whether newer events exist.

Anyone can fetch the instance's public signing key, with no credential:

bash
curl -s "$WEFTRA/api/instance/verification-key"

It returns { key_id, public_key, algorithm }, so a reviewer outside Weftra can check a pack's signature themselves.

On a brand-new instance the pack routes answer 503 signing_key_unavailable until the signing key exists. Weftra creates it the first time it posts a provenance check on a PR or captures a pack at merge, so you only see this before your first PR.

On the pull request ​

Weftra also posts a check named weftra/provenance on the PR's head commit. With a GitHub App credential it is a check-run that carries the whole signed pack. With a personal access token, which can't write check-runs, Weftra posts a commit status instead. Either way, its Details link opens the dashboard's Evidence section for that feature — no credential needed to click it, since it just opens the page; the account you're signed in as still gates what the section shows. When the PR is merged, Weftra saves the signed pack as a feature artifact, evidence-pack.json.

For every field and how to read it, see "Evidence pack", "Verifying a pack" and "The provenance check and verifier" in the User Guide.


Step 11: Iterate on the pull request ​

Review the PR on GitHub as you would any other: comment on lines, request changes. Then have Weftra apply your comments to the same branch. It fetches the PR's review comments, has the agent apply them, runs the tests and pushes to the same branch, so the PR updates in place. The feature goes implemented → revising → implemented.

  • Dashboard: open the feature and click Address PR comments.

  • API:

    bash
    curl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/revise" \
      -H "Authorization: Bearer $PROJECT_API_KEY"
  • IDE or agent console: there is no revise tool. Use the dashboard or the API, then await_feature to wait for implemented again.

If there are no review comments, or something goes wrong, the feature returns to implemented and the PR is left as it was.

When you merge the PR, Weftra notices on its next PR check (every 10 minutes by default, and only with GITHUB_TOKEN set) and marks the feature merged.


Step 12: Build the next feature on unmerged work ​

You don't have to merge the first PR before asking for more. A new feature branches off the project's default branch unless you give it a base_branch. To build an AI opponent on top of the unmerged first version, pass the first feature's branch:

  • Dashboard: in + Submit Feature, fill in Base branch with the first feature's branch name.

  • API:

    bash
    curl -s -X POST "$WEFTRA/api/features" \
      -H "Authorization: Bearer $PROJECT_API_KEY" -H "Content-Type: application/json" \
      -d '{
        "title": "Add a computer opponent",
        "description": "Add a single-player mode against a minimax opponent with alpha-beta pruning and an easy/medium/hard setting. Medium should take no more than 2 seconds per move.",
        "base_branch": "<first feature branch>"
      }' | jq '{id, status}'
  • IDE or agent console: ask the assistant to submit it with base_branch set to the first feature's branch. submit_feature and draft_spec both take base_branch.

The new feature's PR targets that branch too, so its diff shows only the new work.


Optional: a feature-request panel inside the game ​

The original version of this walkthrough had the game itself post feature requests to Weftra. You can still ask for that as a feature, but know what it means first. The panel calls POST /api/features from the browser, so the project key ships in the page's JavaScript. Anyone who can load the page can read it, then submit features and read every feature of the project. Do this only for a copy of the game that stays on your own machine.

If you do:

  • an admin adds the game's origin (for example http://localhost:3000) to Allowed Origins (comma-separated CORS origins) on the project form, or the browser blocks the calls;
  • the panel needs only title and description. A submitter_email it sends is recorded as an unverified claim, not as who submitted.

For anything public, put a small server of your own between the page and Weftra, and keep the key on that server.


Switching to PO approval with an approver ​

Once the game has a solid base, you may want a product owner to approve each feature before the agent starts. These are admin actions.

Change the mode. In the dashboard, click Edit on the project's row, set Autonomy Mode to PO Approval Required and fill in PO Email. With the API:

bash
curl -s -X PATCH "$WEFTRA/api/projects/$PROJECT_ID" \
  -H "Authorization: Bearer $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"autonomy_mode": "po_approval", "po_email": "po@example.com"}' | jq .autonomy_mode

Create an approver and link them to the project. In the dashboard, use + Create User on the Users tab with the Approver role, then switch the user on under Approvers in the project form. With the API:

bash
APPROVER=$(curl -s -X POST "$WEFTRA/api/users" \
  -H "Authorization: Bearer $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"email": "po@example.com", "name": "Product Owner", "role": "approver"}')
APPROVER_ID=$(echo "$APPROVER" | jq -r .id)
echo "$APPROVER" | jq -r .api_key      # the approver's key, shown once

curl -s -X POST "$WEFTRA/api/users/$APPROVER_ID/projects" \
  -H "Authorization: Bearer $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d "{\"project_id\": \"$PROJECT_ID\"}"

Now a new feature waits in awaiting_approval. The approver signs in to the dashboard with their own key, sees only their linked projects, and clicks Approve. Or with the API:

bash
curl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/approve" \
  -H "Authorization: Bearer $APPROVER_API_KEY"

Weftra records the approver from the key; you don't send a name. A project key cannot approve, and neither can an MCP client. A feature's submitter cannot approve their own feature. If you work alone, "Running it on your own" in the quickstart shows how to let a verified account approve its own work and have that recorded.

await_feature does not stop at awaiting_approval by default. An assistant that submitted the feature keeps waiting until the approver acts, or until the wait times out and it asks again.


If a feature fails ​

Features fail for ordinary reasons: an ambiguous request, failing tests, a network error during clone or push, or a run that hits its budget.

  1. Automatic retry. Weftra retries a failed feature up to 3 times (AGENT_MAX_RETRIES).

  2. Retry by hand. In the dashboard, open the feature and click Retry (resumes the preserved workspace) or Retry (fresh clone) (starts again from the latest base branch). With the API:

    bash
    curl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/retry" \
      -H "Authorization: Bearer $PROJECT_API_KEY"
  3. Read what happened. The live log page and the feature view show the run's output. The workspace of a failed run is kept for inspection.

  4. Cancel a run in flight. Cancel run in the feature view, or POST /api/features/:id/cancel. Edit the description and retry.

None of these have MCP tools. The assistant can tell you a feature failed; retry or cancel it in the dashboard or with the API.


What each mode can do ​

StepDashboardAPI (project key)IDE / agent console (MCP)
Survey and enroll a projectYes (admin)Yes (admin key)No. Admin-only. An opt-in named-admin session has create_project, without the survey
Draft a spec with the BuilderYesYesYes
Submit a featureYesYesYes
Answer clarificationsYesYesYes
Approve a feature or a specYes (approver or admin)Approver or admin key onlyNo
Watch the live logYesNo (admin or user credential)No
Create a missing PRYesYesNo
Revise from PR commentsYesYesNo
Read and verify the Evidence PackNot yet (coming)YesNo
Change project settingsYes (admin)Some, for its own project (PATCH /api/project)No

Keep going ​

You now have a loop: describe a change, answer Weftra's questions, review a draft PR with its evidence, and merge what you like. Some next features for the game:

  • "Add move timers for each player (5, 10 and 30 minute options)"
  • "Add sound effects for moves, captures and check"
  • "Add undo and redo"
  • "Show the pieces each player has captured"
  • "Add a replay mode that steps through a finished game"

Where to go next:

  • User Guide: autonomy modes, clarifications, revisions, reviewers, the Evidence Pack, and every setting in depth.
  • Drive Weftra from your assistant: every client, and what to do when one won't connect.
  • Setup guide: notifications, GitHub, GitLab and Bitbucket, users and sign-in, running Weftra in production.
  • Recurring work. If what you need is a worker that runs the same steps on a schedule rather than one feature at a time, see Build your first agent.

Tips ​

  • Say what you want, not how. A clear description with the behaviour you expect gets a better spec. Let Weftra ask about the rest.
  • Review before you merge. The agent is good, not perfect. Read the diff, run the game, and check the Evidence Pack.
  • Protect projects you care about. An admin can set protected: true on a project so it can't be deleted by accident.

Released under the MIT License.