Agents: this page is also Markdown; every page is in llms.txt.
Use Facet from an agent
Facet runs a remote MCP server at https://facet.halfspacelabs.com/mcp. It exposes everything the web app does, so your agent can make a Task, ask for it to get better, start a Change once you approve the quote, and call the result. Facet's own agent does the prompt and training work; your agent only describes what it needs.
Connect
Most clients sign you in with a browser popup (OAuth) the first time; there is no key to paste.
- Claude Code:
claude mcp add --transport http facet https://facet.halfspacelabs.com/mcp, or install the plugin:/plugin marketplace add halfspacelabs/facet-plugins, then/plugin install facet@facet. - Claude (claude.ai and the desktop app): Settings, Connectors, Add custom connector, with the URL above.
- Cursor: use the Add to Cursor button on any Task's Use it panel, or add
{"mcpServers": {"facet": {"url": "https://facet.halfspacelabs.com/mcp"}}}to~/.cursor/mcp.json. - VS Code: use the Add to VS Code button on the Use it panel, or run MCP: Add Server with the URL.
- ChatGPT: Settings, Apps and Connectors, Create, with the URL above (developer mode).
- Codex:
codex mcp add facet --url https://facet.halfspacelabs.com/mcp.
A client that can't sign in can send an API key instead: Authorization: Bearer fct_.... A key acts with its own role and Task scope.
How an agent uses it
create_taskwith a plain description of the job and a few sample inputs. Version 0 is callable at once with the OpenAI SDK; the result says how.file_askwhen the Task should get better, in plain words, with examples of misses. Facet drafts the Expectation, measures Latest and quotes a Change.- Show the person the plan and quote.
approve_planonly with their yes: your client asks them to confirm, because the tool spends money. A Change never spends more than its quote. get_changeto follow it; once it merges, the new Version is Latest.try_versioncalls it once;rollbackundoes a merge in one step.
The use-facet Skill, in the Facet plugin, teaches agents this flow and when Facet fits.
Toolsets and modes
Tools come in toolsets. tasks, changes and versions are on by default; workspace (keys, members, policy, spend limit) is opt in. Pick them with the X-MCP-Toolsets header (tasks,changes, all) or, for clients that only take a URL, the query string: https://facet.halfspacelabs.com/mcp?toolsets=all.
- Read-only mode (
X-MCP-Readonly: trueor?readonly=true) lists only the tools that read. - Lockdown mode (
X-MCP-Lockdown: trueor?lockdown=true) hides text that people or data wrote (Ask requests, examples, model answers, Expectation statements, Instructions) from every result, so nothing a tool returns can carry a prompt injection. Names, numbers, states, scores and quotes stay. - Workspace: you act in your first workspace;
X-MCP-Workspaceor?workspace=picks another by ID.
Every tool follows the same policy as the web app: your role, the Task's rules, the quote cap and the spend limit. Tools that spend money or change who can act are marked destructive, so clients confirm them with you.
Tools
tasks (on by default)
| Tool | What it does |
|---|---|
list_tasks |
List the workspace's Tasks: each one's name, Latest Version, accuracy and status (training, needs approval, failing). Read-only. |
get_task |
A Task's page: Latest Version, its scorecard (each Expectation, passing or failing), open Changes and what needs the person. Read-only. |
create_task |
Make a new Task from a plain description of the job (and sample inputs, if you have them). Facet drafts the name, Instructions and Expectations, then creates the Task; its Version 0 is callable at once through the OpenAI SDK, with the Task name as the model. Drafting takes a minute: if the result says drafting, call create_task again with the draft_id it gave. |
list_expectations |
A Task's Expectations: the checks every Version runs, each with its pass rate. Read-only. |
get_expectation |
One Expectation: its statement, grader, bar and example counts. Read-only. |
add_expectation |
Add an Expectation to a Task. Usually not needed: file_ask drafts the Expectation an Ask implies. |
edit_expectation |
Edit an Expectation. Loosening one waits for a Task owner's approval. |
add_examples |
Add examples (input, and the reference output if there is one) to an Expectation. They train and check only this Task. |
changes (on by default)
| Tool | What it does |
|---|---|
list_changes |
A Task's Changes: each one's number, state (queued, running, ready, merged, failed, closed) and quote. Read-only. |
get_change |
One Change: its steps, spend against its quote, and once Ready what got better and worse. Read-only. |
file_ask |
Ask for a Task to get better at something, in plain words, with examples of where it falls short if you have them. Facet's own agent does the work: it drafts the Expectation the Ask implies, runs it on Latest to show the baseline, and quotes a Change. Nothing is spent until approve_plan. Planning takes a minute: if the result says planning, call get_ask later. |
get_ask |
An Ask: its plan (drafted Expectation, misses on Latest, quote per approach), or the Change it opened. Read-only. |
approve_plan |
Start a Change on an Ask's plan, accepting its quote: the Change spends up to the quote and never more. Show the person the plan and quote first and approve only with their yes. approach is instructions (no training, cheapest) or train. Asks the person to confirm. |
close_ask |
Close an Ask without a Change; add_expectation keeps its drafted Expectation. |
stop_change |
Stop a running Change now. It spends nothing more; Latest stays as it was. |
close_change |
Close a Ready or stopped Change without merging it. |
raise_quote |
Continue a Change that stopped at its quote, with a higher quote. Spends money: only with the person's yes. Asks the person to confirm. |
merge_change |
Merge a Ready Change: its Version becomes Latest, which callers get at once. Rollback undoes it in one step. Asks the person to confirm. |
list_approvals |
Approvals waiting for the signed-in person, such as a merge under Strict merge protection. Read-only. |
answer_approval |
Approve or reject a waiting approval. Only with the person's yes. Asks the person to confirm. |
versions (on by default)
| Tool | What it does |
|---|---|
list_versions |
A Task's Versions, newest first, with which one is Latest. Read-only. |
get_version |
One Version, like a model card: what changed, accuracy, latency, cost and the Expectations it passes and fails. Read-only. |
try_version |
Call a Task's Version once with an input and get its answer, as an app would. Latest unless version is given. Metered like any call. |
rollback |
Point Latest at an earlier Version, or undo the last rollback. One step, always reversible. |
workspace (opt in)
| Tool | What it does |
|---|---|
get_me |
The signed-in person, their workspaces and the base URL Tasks are called on. Read-only. |
get_spend |
This month's spend and the workspace's monthly spend limit. Read-only. |
set_spend_limit |
Set the workspace's monthly spend limit, in micro-dollars. Workspace Owners only. Asks the person to confirm. |
get_usage |
Serving calls and spend per Task this month. Read-only. |
list_members |
The workspace's members and pending invites. Read-only. |
set_member_role |
Change a member's workspace role. Asks the person to confirm. |
remove_member |
Remove a member from the workspace. Asks the person to confirm. |
invite |
Invite someone to the workspace by email. |
withdraw_invite |
Withdraw a pending invite. |
list_keys |
The workspace's API keys (never their secrets). Read-only. |
create_key |
Make an API key for calling Tasks, optionally limited to one Task. The secret is in this result only: hand it to the person or put it in their app's secrets, never in code. |
revoke_key |
Revoke an API key at once. Asks the person to confirm. |
get_task_settings |
A Task's policy: merge protection, who may start Changes, and its owners. Read-only. |
set_task_settings |
Change a Task's policy. Task owners only. Asks the person to confirm. |