> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mellob.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipes

> Automate something with one YAML file — no install, no rebuild.

A recipe is one file in `~/.karmax/recipes/`. Save it and it runs; there is no
install step and no restart, because a tier with an install step is a tier
nobody uses.

```yaml theme={null}
# A morning news digest, ingested to memory.
name: tech-news
on:
  schedule: "0 9 * * *"

steps:
  - harness: >
      Compile a daily digest of notable news from the last 24 hours in AI,
      developer tooling and security. 5-8 items, one line each plus the source.
      Output ONLY the digest.
    as: digest

  - when: "{{ .digest }}"
    remember:
      fact: "Tech news digest: {{ .digest }}"
    else:
      - log: "tech-news: the harness returned nothing usable"
```

That is a complete, working automation. It has a schedule, it calls a model, it
binds the result, it checks the result was real, and it writes to memory.

## Triggers

```yaml theme={null}
on:
  schedule: "0 9 * * *"      # five-field crontab, or six with seconds
  event: comms.message        # something happened inside KARMAX
  webhook: /hooks/deploy      # an HTTP POST from outside
  manual: true                # only when you run it
```

<Tip>
  Cron takes **five fields**, the syntax everyone writes. Six is also accepted if
  you need seconds (`"0 0 9 * * *"`). Shorthands work too: `@every 45m`, `@daily`.
  An expression KARMAX cannot run is rejected when the file is saved, not silently
  at 9am on a morning it does not fire.
</Tip>

## Steps

Exactly one verb per step, so the file reads top to bottom and there is never a
question about what runs first.

| Verb       | Does                                             | Returns something? |
| ---------- | ------------------------------------------------ | ------------------ |
| `ask`      | Your agent, with all of its tools and judgement  | yes                |
| `harness`  | A coding harness — shell, files, web research    | yes                |
| `gateway`  | The main model directly, no agent loop. Cheapest | yes                |
| `http`     | Fetch something                                  | yes                |
| `tool`     | Call a KARMAX tool by name                       | yes                |
| `recall`   | Read long-term memory                            | yes                |
| `remember` | Write to long-term memory                        | no                 |
| `notify`   | Tell you                                         | no                 |
| `propose`  | Ask you to approve an action                     | no                 |
| `remind`   | Put something on your list                       | no                 |
| `send`     | Message someone on WhatsApp                      | no                 |
| `sleep`    | Durable wait — the run parks and resumes later   | no                 |
| `log`      | Write a line to KARMAX's log                     | no                 |

Only the verbs that return something can be bound with `as`.

### Binding and using results

```yaml theme={null}
steps:
  - recall: "what did we agree with the vendor"
    as: context

  - gateway: "Summarise this in two lines: {{ .context }}"
    as: summary

  - notify:
      title: "Vendor"
      body: "{{ .summary }}"
```

### Conditions

```yaml theme={null}
  - when: "{{ .digest }}"        # runs when the binding is non-empty
    notify:
      title: "Digest"
      body: "{{ .digest }}"
    else:
      - log: "nothing to report"
```

### Waiting for days

```yaml theme={null}
  - sleep: 72h
  - ask: "Did the client ever reply about the invoice?"
```

`sleep` parks the run in a durable timer rather than holding a goroutine, so
hours and days are fine and a restart does not lose it.

### HTTP headers

Headers are flat, one per line:

```yaml theme={null}
  - http:
      url: https://api.example.com/status
      header.Authorization: Bearer ${TOKEN}
    as: status
```

<Warning>
  A nested `headers:` block is rejected rather than silently ignored — it is the
  obvious thing to write and the wrong thing, so the error says so and shows the
  flat form.
</Warning>

## Checking your work

```bash theme={null}
karmax recipe check          # validate every recipe
karmax recipe test <name>    # show what it WOULD do, without doing any of it
karmax recipe example        # print one to start from
karmax loops run <name>      # run it now
```

Errors point at a line and suggest a fix:

```
~/.karmax/recipes/digest.yaml:5: steps must be a list
  try: each step starts with '- ' on its own line
```

## When to reach for a workflow instead

A recipe is a schedule and some steps. When you need real control flow, state
across runs, or tools of your own, that is a [WASM workflow](/karmax/dev/workflows)
— sandboxed code with a capability manifest. Most automations are not that, and
reaching for it first is how you end up maintaining a program where a file would
have done.
