Build a custom machine
Concepts
The door
A machine imports one thing of the Ownbox's, from core import sdk, and sdk.machine("<slug>") hands back the machine
object, m. Every call on m crosses the door to the Ownbox, which answers it under what the owner allowed. The
same code runs unchanged on your computer, in the Ownbox's dry runs, and installed.
Permissions, asked and granted
machine.yaml asks, under permissions:, for exactly what the machine touches. Nothing is allowed unless it is named
there. The owner sees every line on the review card in plain words before the machine runs. What the owner grants is
never more than the machine asked for. A call outside the grant is refused not_permitted, and the refusal names the
line to add.
The review card
The card that holds a finished build until a person decides. It shows what the machine asks for, each permission in plain words, the packages it installs, how its tests went, and what it costs. A line that reaches outside the Ownbox or changes its records is marked for the owner's attention. Nothing installs until a person taps Approve, and Approve holds only for the exact code, version and permissions the card showed.
Dry runs
Before the owner is asked, the Ownbox runs the draft twice, never both at once. The data run reads the owner's real data and reaches nothing. The fetch run reaches only the hosts the owner tapped for the test, and reads a sample business instead of theirs. See Testing.
Step keys and service keys
Two different things share the word key. A step key is the key= argument on every call that acts (send_dm,
reply_to_comment, send_email, notify, spend): it names the step, and the same key again within a day is
answered with the first answer, so a retry never acts twice. A service key is a secret for another company's API,
listed under keys: in machine.yaml. The owner enters it on the machine's Keys page, and the Ownbox attaches it to
m.fetch(url, key="<name>") on the way out. The machine never sees it.
Answers and refusals
A call the Ownbox will not make raises sdk.BoxRefused, whose .code says why: the grant does not cover it, or it
is past a limit. A call the grant covers answers its outcome instead: the people, conversation and send calls carry a
status and a code, because "not sent" is a normal outcome a machine decides on. Read the status; never assume a
send went.
The local Ownbox
The Ownbox ownbox run and ownbox preview start on your computer. It answers every call as an Ownbox does in a fetch
run where the owner tapped nothing: the business's data comes from a sample, the AI answers one fixed sentence, a fetch
is checked and then refused not_tapped, and every send, spend and proposal is listed as what it would have done.
Partner Ownboxes
On a partner's Ownbox, Ownbox reviews a machine as well as the owner. The owner's Approve sends the sealed build to Ownbox, which reviews that exact code and says yes, or no with the reason. It installs only on Ownbox's yes, and the yes covers only that code.