# SDK at a glance

Part of [Build a custom machine](https://www.ownbox.io/sdk/guide).

Every call, grouped as the SDK reference groups them. *Needs* is the line machine.yaml must hold; a dash means
nothing. Each name links to its full entry in the SDK reference.

**The machine**

| Call | Needs | Does |
|---|---|---|
| `sdk.machine(slug)` | — | The machine object, `m`, for the folder's own slug. |
| `m.home` | — | Its own address on the Ownbox, `/my/<slug>`. |

**Settings and files**

| Call | Needs | Does |
|---|---|---|
| `m.setting(key, default=None)` | — | Reads a value it saved, or `default`. |
| `m.save_setting(key, value)` | — | Saves a value, as JSON. |
| `m.data_dir()` | — | Its own folder, for an SQLite file and larger files. |

**Jobs**

| Call | Needs | Does |
|---|---|---|
| `m.every(seconds, *, name=None)` | — | Runs the decorated function on a schedule; the first run is due at once. |

**The AI**

| Call | Needs | Does |
|---|---|---|
| `m.think(task, prompt, *, system=None, max_tokens=1024)` | `think` | Asks the Ownbox's AI, metered under its monthly allowance. |

**The web and keys**

| Call | Needs | Does |
|---|---|---|
| `m.fetch(url, *, method="GET", headers=None, body=None, key=None, timeout=20)` | `fetch`, and `keys` for `key=` | Makes one https request, through the Ownbox. |
| `m.keys_page` | — | The owner's page for this machine's keys and their monthly limits. |
| `m.secret(name, *, label=None, help="")` | — | Always refused `never_readable`: a machine never reads a key. |

**People**

| Call | Needs | Does |
|---|---|---|
| `m.person(kind, value, *, name="", space=None)` | `people:write` | The person behind an id, made the first time any machine meets them. |
| `m.touch(person, kind, ref="")` | `people:write` | Records an event on their timeline. |
| `m.people_find(q=None, *, kind=None, limit=50, cursor=None, space=None)` | `people:read` | The people the business met, a page at a time. |
| `m.people_timeline(person, *, limit=50, cursor=None)` | `people:read` | What happened to one person, newest first. |
| `on_forget(person_id)` | `on_forget: true` | A function the machine defines: erases one person from its own data. |

**Conversations**

| Call | Needs | Does |
|---|---|---|
| `m.messages(conversation, *, since=None)` | `conversations:read` | A conversation's messages, oldest first. |
| `m.comments(*, post=None, since=None)` | `conversations:read` | Recent comments on the business's Instagram account. |
| `m.conversation_for(comment)` | `conversations:read` | The direct-message conversation with whoever wrote a comment. |
| `m.follows_you(conversation)` | `conversations:read` | Whether they follow the account: `True`, `False` or `None`. |
| `m.claim(conversation, *, title, days=7, trigger=None)` | `conversations:write` | Takes charge of a conversation in the inbox. |
| `m.release(conversation, *, note="")` | `conversations:write` | Lets it go, or hands it to the team with a note. |

**Sending**

| Call | Needs | Does |
|---|---|---|
| `m.send_dm(conversation, text, *, key, buttons=None, quick_replies=None)` | `send: dm` | One message on a conversation it claimed. |
| `m.reply_to_comment(comment, text, *, key, quick_replies=None)` | `send: dm` | A private reply to a comment. |
| `m.send_email(person, draft, *, key, consent=None)` | `send: email` | One email to a person who wrote in first. |
| `m.drafts(*, limit=50)` | — | The emails the Ownbox kept for the owner to send. |
| `m.drop_draft(draft_id)` | — | Lets one of its drafts go. |

**The team and money**

| Call | Needs | Does |
|---|---|---|
| `m.notify(member, text, *, key="notice")` | — | Tells one team member one thing, in the next notice slot. |
| `m.spend(vendor, units=1, *, key)` | `keys`, and the owner's monthly limit | Records a paid unit before the call that spends it. |

**Approvals**

| Call | Needs | Does |
|---|---|---|
| `m.propose(kind, *, title, detail=None)` | — | Holds an action on Approvals until a person decides. |
| `m.on_approve(kind, fn)` | — | Registers what runs, once, when a person says yes. |

**The owner's AI and the Morning Review**

| Call | Needs | Does |
|---|---|---|
| `m.tool(name, *, fn, description, args=None, title=None, render=None)` | — | A question the owner's AI may ask the machine. |
| `m.reporter(title, fn)` | — | Its part of the owner's Morning Review. |
| `m.day_window(day)` | — | The UTC bounds of one of the Ownbox's local days. |

**Pages and cards**

| Call | Needs | Does |
|---|---|---|
| `m.screen(path, *, owner_only=False, title=None)` | — | Declares a page at `m.home` or under it; the decorated function answers it. |
| `m.panel(slot, *, title, render)` | — | Declares a card on another screen. |
| `m.link(path)` | — | The full address of one of its pages. |
| `sdk.page(path, *, title, lede="", body)` | — | A page as HTML, for a machine written before screen.json. |

**Not yet.** `m.menu` and `m.activity` raise `sdk.NotYet` with a sentence. `m.store`, `m.query`, `m.media` and
`m.upload` are reserved for later releases and raise `sdk.Reserved`, saying what to use until then.

`m.tool` also takes `capability=`, which only a machine that runs in-process uses: a custom machine's tool always
runs under the capability the Ownbox gives it, `read:my_<key>` ([Routes and tools](https://www.ownbox.io/sdk/guide/routes-and-tools)).
