A gateway in your loop
Keep your model, agent loop, UI, and existing tools. Add one execute tool as the gateway to everything smallworld exposes.
Connect them to your customers' apps, data, and APIs through one governed terminal. Credentials, policy, and approvals included.
Structured tools repeat the workflow page by page. smallworld lets the agent compose the whole job in Bash.
Structured tools
Set the Status of every page in Content calendar to Published.
Bash
Set the Status of every page in Content calendar to Published.
Your backend owns the model loop and customer experience. Add one execute tool; smallworld runs the durable terminal behind it, connecting each end user’s accounts through the policy you set for that agent.
Merge the pull request linked to “Retry failed imports” and move the backlog item to Done.
Done. I merged PR #482 and moved “Retry failed imports” to Done in Notion.
import { Agent, run, tool } from "@openai/agents";import { z } from "zod";const sessionId = await sessionFor(endUser.id);const apiKey = process.env.SMALLWORLD_API_KEY;const execUrl = `${SMALLWORLD_URL}/v1/worlds/` + `${WORLD_ID}/sessions/${sessionId}/exec`;const execute = tool({ name: "execute", parameters: z.object({ command: z.string() }), async execute({ command }) { const job = await fetch(execUrl, { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ command, mode: "sync" }), }).then((res) => res.json()); if (job.status === "awaiting_approval") await publishApproval(job); return await waitForCompletion(job); },});const agent = new Agent({ instructions: worldPrompt, model: process.env.OPENAI_MODEL, tools: [execute],});await run(agent, message);notion database item get \ --database "Product backlog" \ --name "Retry failed imports"
github pull-request merge \ --repo acme/web \ --number 482 \ --method squash
notion page update \ --page "Retry failed imports" \ --status Done
Keep your model, agent loop, UI, and existing tools. Add one execute tool as the gateway to everything smallworld exposes.
Use pipes, files, and saved session state. The model doesn’t need to handle every step.
Keep credentials outside the model. Allow, ask, or deny every operation on user or world level.
When joins and business rules outgrow a shell pipeline, use JavaScript or Python. Customer records and SLA rules turn 86 orders into a 14-order review queue, with 4 exceptions kept for follow-up.
/workspace
01import json02from datetime import datetime, timedelta, timezone03from pathlib import Path0405def load(name):06 path = Path("input") / f"{name}.json"07 return json.loads(path.read_text())0809def save(name, rows):10 path = Path("output") / f"{name}.json"11 path.write_text(json.dumps(rows, indent=2))1213orders = load("orders")14customers = {c["id"]: c for c in load("customers")}15rules = load("sla-rules")16now = datetime.now(timezone.utc)17queue, exceptions = [], []1819for order in orders:20 customer = customers.get(order.get("customer_id"))21 rule = rules.get(customer.get("tier")) if customer else None22 if not rule:23 exceptions.append({24 "order_id": order["id"],25 "reason": "missing_customer_or_sla",26 })27 continue28 opened = datetime.fromisoformat(order["opened_at"].replace("Z", "+00:00"))29 due = opened + timedelta(hours=rule["response_hours"])30 high_value = order["amount_cents"] >= rule["review_over_cents"]31 if due <= now + timedelta(hours=4) or high_value:32 queue.append({33 "order_id": order["id"],34 "owner": customer["owner"],35 "due_at": due.isoformat(),36 })3738queue.sort(key=lambda item: item["due_at"])39save("priority", queue)40save("exceptions", exceptions)/workspace
Command log
notion database query--id orders-db > input/orders.json · 86 pages
hubspot company list--properties tier,owner > input/customers.json · 61 records
python scripts/build_queue.pyexit 0 · 14 priority orders · 4 exceptions
fs.writereports/priority-page.json · 1.8 KB
notion page create--file reports/priority-page.json · allowed
fs.commitsnapshot v12 · 7 files · 18.4 KB
Oversized stdout is materialized as a virtual file.
After every execution, smallworld saves a versioned virtual-filesystem snapshot. Return to the same World and represented user, and the session resumes with the same files.
Give each World the providers and operations its workflows need. End users connect accounts once in the Workspace; your agent keeps the same execute tool across the entire catalog.
Select the providers and operations this World may use.
Reuse one user connection wherever that provider is enabled.
One unchanged interface. Your agent sees only the commands available to that World and user through the same execute tool.
Set a default for the World, then override individual operations. Each call is allowed, sent for approval, or denied before credentials attach.
The catalog defines each approval. It applies only to the paused operation.
| Operation | Class | Result |
|---|---|---|
| Read customer record | Read | Allow |
| Update campaign | Reversible write | Allow |
| Merge pull request | Destructive | Ask |
| Change organization settings | Admin | Ask |
| Unclassified operation | Unknown | Deny |
smallworld checks policy first, then its credential broker authenticates only the permitted provider call. The credential never enters the World.
Inside the World · no credentials
Credential boundary and provider
Inside the World
01A named operation and its arguments.
The World allows, asks, or denies.
Outside the World
03Only the permitted provider call.
Credential attaches here
The brokered request.
Create a World, run its first command, and connect customer accounts only when a workflow needs them.