Drafts API
Turn on drafts, read the draft state of a session and control draft work from your own program. The agent in the session still creates, approves and discards each draft.
The examples use the Python SDK. To see the same steps as HTTP API requests, select HTTP at the top of the page.
When to use
- A setup script must protect the checkouts of a project. Turn on drafts for that project.
- A dashboard must show whether a session works in a draft, and what changed. Read the draft state.
- A batch job must make a change that a person reviews first. Ask for work in a draft, then approve or discard the draft after the review.
- A session works in the wrong directory. Return to the original checkout.
To learn how drafts isolate changes, read Drafts.
Before you start
Python
Connect a GatewayClient as in Connect to a gateway and run a
task. The examples use client and session, a
Session from client.session(session_id).
HTTP
Define the vis_api function from Authenticate requests. The
examples use it. They also use SESSION_ID for the ID of a session that you created or found.
Drafts are experimental and off by default. Approval commits and can push. Your program must have the permission of the person who owns the repository.
Operations
Python
Typed calls check the answers and return records. Generated methods return the JSON answer of one request.
| Task | Typed call | Generated method |
|---|---|---|
| Turn on drafts | — | post_settings(body=...) |
| Read the draft state | — | get_session_workspace(sid) |
| Ask for work in a draft | session.send(request) |
post_session_turns(sid, body=...) |
| Approve or discard a draft | session.send(request) |
post_session_turns(sid, body=...) |
| Return to the original checkout | — | patch_session_workspace_root(sid, body=...) |
HTTP
| Task | Method and path |
|---|---|
| Turn on drafts | POST /v1/settings |
| Read the draft state | GET /v1/sessions/{sid}/workspace |
| Ask for work in a draft | POST /v1/sessions/{sid}/turns |
| Approve or discard a draft | POST /v1/sessions/{sid}/turns |
| Return to the original checkout | PATCH /v1/sessions/{sid}/workspace/root |
Turn on drafts
Python
client.post_settings(
body={"scope": "project", "target_id": project_id, "id": "draft_backend", "action": "value", "value": "auto"}
)
HTTP
vis_api -X POST "$VIS_GATEWAY_URL/v1/settings" -H 'content-type: application/json' --data "{\"scope\": \"project\",
\"target_id\": \"$PROJECT_ID\", \"id\": \"draft_backend\", \"action\": \"value\", \"value\": \"auto\"}"
The draft_backend setting is off, auto, worktree or rift. Enable drafts
explains each backend. Configuration API explains
the scopes.
Read the draft state
Python
workspace = client.get_session_workspace(session.id)["workspace"]
print(workspace["is_draft"], workspace["root"], workspace["repo_root"])
print(workspace.get("branch"), workspace.get("draft_changes"))
The answer has the root of the session, the repo_root of its project and the git state. In a
draft, it also has the draft branch, the repositories, the draft_changes and the
working_changes. These summaries refresh in the background. A summary that is not ready yet is
missing, never zero.
HTTP
vis_api "$VIS_GATEWAY_URL/v1/sessions/$SESSION_ID/workspace"
The answer has workspace with the root of the session, the repo_root of its project, is_draft
and the git state. In a draft, it also has the draft branch, the repositories, the
draft_changes and the working_changes. These summaries refresh in the background. A summary that
is not ready yet is missing, never zero.
recovery_required is true when the session opened a directory of another draft. draft_error
then explains the problem.
Ask for work in a draft
Python
turn = session.send("Fix the parser and run the tests. Do not commit or push until I approve.")
print(turn.wait(timeout=1800)["status"])
HTTP
vis_api -X POST "$VIS_GATEWAY_URL/v1/sessions/$SESSION_ID/turns" -H 'content-type: application/json' \
--data '{"request": "Fix the parser and run the tests. Do not commit or push until I approve.", "idempotency_key": "parser-1"}'
With drafts on, the agent starts each change in a draft of its own. Your files stay unchanged.
Approve or discard a draft
Python
session.send("Show me the diff of the draft.").wait(timeout=300)
session.send("Approve the draft.").wait(timeout=600)
HTTP
vis_api -X POST "$VIS_GATEWAY_URL/v1/sessions/$SESSION_ID/turns" -H 'content-type: application/json' \
--data '{"request": "Approve the draft.", "idempotency_key": "parser-approve-1"}'
Approval commits the changes, moves the target branch forward and pushes when origin is
configured. To drop the changes, send Discard the draft. instead. Unapproved changes are then lost.
Approval explains the checks before a commit.
Return to the original checkout
Python
workspace = client.patch_session_workspace_root(session.id, body={"path": "/Users/me/projects/app"})
print(workspace["workspace"]["root"])
This call does the same as /cd. It moves the session to another directory and returns the new
workspace. The directory of the draft and its files stay unchanged.
HTTP
vis_api -X PATCH "$VIS_GATEWAY_URL/v1/sessions/$SESSION_ID/workspace/root" \
-H 'content-type: application/json' --data '{"path": "/Users/me/projects/app"}'
This request does the same as /cd. It moves the session to another directory and returns the new
workspace. The directory of the draft and its files stay unchanged.
See also
- Drafts — backends, approval and recovery.
- Python SDK — install the SDK, connect a client and handle gateway errors.
- HTTP API — authentication, the OpenAPI document and gateway errors.
