# Entry points

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

What the Ownbox calls in the machine, and when. Each runs in the machine's own unit.

| Entry point | Declared with | The Ownbox calls it | Time limit |
|---|---|---|---|
| A job | `@m.every(seconds)` | at its time; as soon as the machine starts; when a person taps its button | — |
| A page | `@m.screen(path)` | each time a person opens the page | 20 s |
| A card | `m.panel(slot, title=, render=)` | each time the screen with that slot is drawn | 20 s |
| A tool | `m.tool(name, fn=, ...)` | when the owner's AI asks it | 60 s |
| A Morning Review part | `m.reporter(title, fn)` | once a pass; the latest answer is shown | — |
| An approval | `m.on_approve(kind, fn)` | once, after a person says yes to its proposal | — |
| A forget | `def on_forget(person_id)` | when the owner erases a person (not called yet) | — |

- **A job** runs every 15 seconds to once a week. A run that raises is reported, and the next one goes ahead.
- **A page or a card** that does not answer within 20 seconds shows *This machine did not answer in time*, with a
  Try again button.
- **A tool's** answer reaches the owner's AI quoted, as the machine's own words, at most 8 KB. `render(result)` writes
  it in words; each argument is a string of at most 500 characters, a whole number or a true/false.
- **A Morning Review part** answers `fn(day)` with `{"title", "headline": {"value", "label"}, ...}`, or `{}` to show
  nothing that day. A slow part never holds the review up.
- **`on_forget`** is not called yet: erasing a person on the Ownbox does not reach a machine's own data until it is.
  Write it now. A machine that names people data is refused without it.
