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:
- Create a repository with a single README.
- Enroll it in Weftra, letting Weftra survey the repository first.
- Describe the game and let Weftra write the spec, ask you questions and build it.
- Watch the run, review the branch, the draft pull request and the signed Evidence Pack.
- 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 Weftra | What it is | Credential |
|---|---|---|
| Dashboard | The web UI at http://localhost:3100 | An admin, approver or user account (the dashboard does not accept a project key) |
| API | curl against the same routes the dashboard uses | The project key (fa_...). The admin key only where a route needs it |
| In an IDE | Claude Code in VS Code or Cursor, talking to Weftra over MCP | The project key, read from your environment |
| In an agent console | The Claude Code CLI over MCP, or claude.ai and ChatGPT as remote connectors | The 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) andnpm 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_TOKENso Weftra can open draft pull requests. The quickstart's Prerequisites list the token's scopes. - The admin key (
ADMIN_API_KEYin.env). You need it once, to enroll the project.
Then, for the mode you want:
| Mode | Also needs | Where to set it up |
|---|---|---|
| Dashboard | A browser | Nothing more |
| API | curl and jq | Nothing more |
| In an IDE | Claude Code installed in VS Code or Cursor | Claude Code docs, then "Claude Code" in Drive Weftra from your assistant |
| Claude Code CLI | Claude Code installed | Claude Code docs, then "Claude Code" in Drive Weftra from your assistant |
| claude.ai or ChatGPT | Weftra 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.
# 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-gameAdd a README and push it:
echo "# My Chess Game" > README.md
git add README.md
git commit -m "Initial commit"
git push -u origin mainOn 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:
cd /path/to/weftra
npm run build && npm startYou should see:
[weftra] API server running on 127.0.0.1:3100Weftra 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:
export WEFTRA=http://localhost:3100
export ADMIN_API_KEY=... # the value in Weftra's .envStep 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
Open
http://localhost:3100, paste the admin key into the login box and click Sign In with API Key.On the Projects tab, click + Enroll Project.
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.Set Autonomy Mode to Auto + Safety (
auto_safe). Step 4 explains why.Tick Auto-create Draft PRs if you set
GITHUB_TOKEN.Click Save.
Weftra shows the project key once, in a pop-up. Copy it now:
bashexport 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):
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:
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:
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:
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):
| Mode | Dashboard label | What happens to a new feature | Who answers Weftra's questions |
|---|---|---|---|
full_auto | Full Auto | Goes straight to the queue. No analysis, so no questions | Nobody is asked |
auto_safe | Auto + Safety | Weftra analyzes it first and may ask questions. The feature waits in clarification_needed until they're answered | You |
po_approval | PO Approval Required | Waits in awaiting_approval for an approver, then is analyzed like auto_safe | You |
full_auto_analyze | Full Auto + Unattended Analyze (experimental) | Analyzed, and a sandboxed answerer replies for you | An automatic answerer |
This walkthrough uses auto_safe, so you see the question-and-answer loop.
What you send with the feature:
| You send | What Weftra does |
|---|---|
A short description of what you want | Weftra 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 gets403. - Require spec approval (
require_spec_approval). When Weftra wrote the spec (you sent nospec_content), the run pauses inawaiting_spec_approvalbefore 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:
export FA_PROJECT_API_KEY="$PROJECT_API_KEY" # in your shell profile or a secrets managerClaude 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:
{
"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
claudein the repository, approve theweftraserver when asked, and run/mcpto check that it's connected. - VS Code or Cursor: open the repository, start Claude Code from the editor, approve the
weftraserver, and check it with/mcp. Start the editor from a shell whereFA_PROJECT_API_KEYis 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:
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.comThen 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
| Tool | What it does |
|---|---|
draft_spec, clarify_spec, refine_spec, estimate_spec | Weftra's Builder: draft a spec from plain English, ask questions before anything is submitted, revise a draft, estimate its cost and scope |
submit_feature | Submit the feature |
get_feature_status, list_features | Read a feature's status, branch and PR link |
await_feature | Wait 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_clarification | Read Weftra's open questions and answer them |
list_projects | Show 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) andjs/app.js. Add apackage.jsonwhosenpm startserves the files and whosenpm testruns 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:
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:
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:
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:
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:
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
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
cd my-chess-game
git fetch origin
git checkout <branch name> # the feature's branch_name, feature/<slug>-<id>
npm install
npm test
npm startYou 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:
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:
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 }):
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.jsonAs a page you can read:
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:
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 @- | jqThe 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:
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:
bashcurl -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_featureto wait forimplementedagain.
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:
bashcurl -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_branchset to the first feature's branch.submit_featureanddraft_specboth takebase_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
titleanddescription. Asubmitter_emailit 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:
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_modeCreate 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:
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:
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.
Automatic retry. Weftra retries a failed feature up to 3 times (
AGENT_MAX_RETRIES).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:
bashcurl -s -X POST "$WEFTRA/api/features/$FEATURE_ID/retry" \ -H "Authorization: Bearer $PROJECT_API_KEY"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.
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
| Step | Dashboard | API (project key) | IDE / agent console (MCP) |
|---|---|---|---|
| Survey and enroll a project | Yes (admin) | Yes (admin key) | No. Admin-only. An opt-in named-admin session has create_project, without the survey |
| Draft a spec with the Builder | Yes | Yes | Yes |
| Submit a feature | Yes | Yes | Yes |
| Answer clarifications | Yes | Yes | Yes |
| Approve a feature or a spec | Yes (approver or admin) | Approver or admin key only | No |
| Watch the live log | Yes | No (admin or user credential) | No |
| Create a missing PR | Yes | Yes | No |
| Revise from PR comments | Yes | Yes | No |
| Read and verify the Evidence Pack | Not yet (coming) | Yes | No |
| Change project settings | Yes (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: trueon a project so it can't be deleted by accident.