Volter World

GitHub issue to Linear ticket and Slack update

Give a tool-using agent an isolated workplace: a GitHub repository and source issue, a Linear team and existing runbook task, and a Slack triage channel with a policy message. The starter reads an issue, creates a linked ticket and posts the result to the channel through the real SDKs.

This application uses a labeled fixed policy: titles beginning with P1: receive priority 1; other titles receive priority 3. It exercises tools and stored outcomes. To assess an agent's planning or judgment, replace that decision with your own agent and configure its model twin's scripted answers separately. A successful fixed-rule handoff does not assess a model.

You need Node 22.6+, npm and registry access during installation. No platform account, private application checkout or real vendor key is required.

Prepare an ordinary workplace

This starter pins GitHub 3.0.9, Linear 3.0.5 and Slack 3.0.8. A catalog page may select a newer default. Keep this example's manifest and installation lock together; its recorded workflow does not establish behavior for a different release.

$ npx @volter/world@3.0.158 example workplace-agent --dir workplace
$ cd workplace
$ npm install
$ ./node_modules/.bin/volter world init --name workplace --twins github,linear,slack

Read package.json, package-lock.json and clients.mjs for exact tool, twin and SDK versions. Keep the lockfile created by your installation. Review the three configured vendors and synthetic credentials before booting. No model vendor is selected by this starter.

$ ./node_modules/.bin/volter world up
$ ./node_modules/.bin/volter world clock set 2026-01-15T12:00:00Z
$ ./node_modules/.bin/volter world run -- node seed.mjs

seed.mjs creates stored records through each vendor's API. Run it once per fresh or reset World. It writes company.json with the returned repository owner, issue number, team and channel IDs. Existing runbook and policy records give your agent something to read before acting.

Complete a handoff

$ ./node_modules/.bin/volter world run -- node handoff.mjs
$ ./node_modules/.bin/volter world run -- node operate.mjs read
$ ./node_modules/.bin/volter world log
$ ./node_modules/.bin/volter world diff

Read the ticket's title, priority and team, then the channel and posted source/ticket links. handoff.mjs writes an application receipt under outcomes/ as soon as the ticket exists. A repeated completed handoff prints that receipt; it does not create another ticket. operate.mjs reads the vendor's stored result rather than trusting the receipt alone.

Give the task to your coding agent

Install the World skill and MCP tools into your agent's configuration:

$ ./node_modules/.bin/volter agents install

If you already completed the example handoff, create another source issue with world run -- node operate.mjs issue. Give your agent that returned issue number and this task:

Read this starter's README and company.json. Work in its existing World. Read the source GitHub issue, the Linear backlog and the Slack policy message using the installed real SDKs inside volter world run. Apply the supplied priority policy, create a ticket with the source link, then notify the channel with both links. Preserve an application receipt as soon as the ticket exists. If notification is refused, report the stored ticket and pending notification separately. Read the resulting vendor records and show the World log; do not claim success from the script's exit alone. Inspect existing receipts before repeating a mutation.

The agent uses the same public SDKs as clients.mjs; the coding-agent guide owns CLI/MCP setup. You can leave the fixed policy in place to exercise tool use, or supply your own agent decision and model scenario. The requested outcomes are stored links, team, priority and completion state; a scripted response still does not measure model judgment.

Keep a partial result and retry it

Archive the channel, then create another source issue:

$ ./node_modules/.bin/volter world run -- node operate.mjs archive
$ ./node_modules/.bin/volter world run -- node operate.mjs issue

Use the returned issue number in both commands below:

$ ./node_modules/.bin/volter world run -- node handoff.mjs <issue-number>
$ ./node_modules/.bin/volter world run -- node operate.mjs read <issue-number>

Slack's archived-channel refusal leaves the Linear ticket stored. The application reports partial-ticket-created-notification-failed and preserves the vendor error in its receipt. Unarchive the channel and resume that same handoff:

$ ./node_modules/.bin/volter world run -- node operate.mjs unarchive
$ ./node_modules/.bin/volter world run -- node handoff.mjs <issue-number>
$ ./node_modules/.bin/volter world run -- node operate.mjs read <issue-number>

The retry uses the recorded ticket and attempts only the notification. An uncertain process exit between a successful vendor call and writing its receipt requires inspecting the vendor before retrying; this example does not claim exactly-once external execution.

company.json and outcomes/ are application files outside declared World services. They are not branched or reset with vendor history. After explicitly resetting this disposable World, clear only this example's receipts with node reset-receipts.mjs, restore the frozen clock, then seed again. Do not reuse receipts from one World with another.

Inspect Slack's local member screen

The Slack twin provides workspace administration screens. They are separate from Slack's chat UI; read the handoff's ticket and channel messages with operate.mjs read as shown above.

Stop the running World before starting its viewer. The viewer resumes the retained records and keeps running in the background:

$ ./node_modules/.bin/volter world down
$ ./node_modules/.bin/volter world view --no-open &
$ workplace_view_pid=$!

Open the printed console link. Select Slack under Records, then Its screens. Choose Sign in to Slack and enter the synthetic default owner's address, owner@world.test. The screen asks for a confirmation code. Read the twin's captured mail in another terminal, from this app folder:

$ ./node_modules/.bin/volter world run -- node read-slack-mail.mjs owner@world.test

read-slack-mail.mjs reads Slack's declared local /_twin/mail endpoint. Enter the code from the latest message and continue to Manage members, where World Owner appears as the active primary owner. This uses synthetic local identity; no real Slack account or email delivery is involved. This walkthrough covers sign-in and the member list, not invitations or other administration actions.

When finished, stop the viewer you started and retain the workplace:

$ kill -INT "$workplace_view_pid"
$ ./node_modules/.bin/volter world down

Create a synthetic GitHub organization

Personal repositories use GitHub's ordinary create-repository API. Organization creation is a settings-page operation; this twin provides the declared POST /_twin/orgs endpoint for synthetic setup. create-organization.mjs discovers the authenticated account and sends:

{
  "login": "example-payments",
  "name": "Example Payments",
  "owner": "<login returned by GitHub users.getAuthenticated()>",
  "billing_email": "owner@example.invalid"
}

It expects HTTP 201 with the organization's login and id, then creates a private repository using github.repos.createInOrg. Run it once in this World:

$ ./node_modules/.bin/volter world run -- node create-organization.mjs

Without the owner or signed-in browser identity, the settings operation can redirect to sign-in. Inspect GET /twin for its declared setup endpoints rather than guessing a request body or inserting state files.

Stop with ./node_modules/.bin/volter world down to retain the workplace. Inspect a World shows its vendor screens, semantic relations and event history. Failure handoff describes how to share source, clock, handlers and application receipt conditions. Source files identify the starter. The source instructions carry no new execution claim.

View Markdown source

On this page