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

# Tutorial: Pausable Agents

> agent, start, pause, resume, and ask_human, hands-on — a runtime entity that waits on a human, mid-task.

You'll build an agent that starts, does some work, pauses to wait for a
human decision, and resumes from exactly where it left off. Nothing here
needs an API key.

## 1. Declare and start an agent

`agent name: ...` only declares — nothing runs until `start(agent)`. A
plain `agent` blocks until its body finishes:

```sns theme={null}
agent analyst:
    print("analyzing...")
    finding = "checkout latency is up 40%"

print(analyst.status)
start(analyst)
print(analyst.status)
print(analyst.finding)
```

```txt theme={null}
created
analyzing...
completed
checkout latency is up 40%
```

`analyst.finding` reads a variable the body set — an agent's own scope
stays inspectable after it runs, like a module's.

## 2. Pause mid-task

`pause(reason?)` suspends the agent right where it's called. `start()`
returns as soon as that happens — it doesn't wait for the agent to
finish, because it might not, for a while:

```sns theme={null}
agent approver:
    print("preparing request...")
    pause("need approval to proceed")
    print("this only runs after resume()")

start(approver)
print(approver.status)
print(approver.pause_reason)
```

```txt theme={null}
preparing request...
paused
need approval to proceed
```

Notice `"this only runs after resume()"` never printed — the agent is
genuinely suspended, not just slow.

## 3. Resume it

`resume(agent, value?)` continues the agent from exactly where `pause()`
left it. Whatever you pass becomes `pause()`'s own return value inside the
agent body:

```sns theme={null}
agent approver:
    print("preparing request...")
    answer = pause("need approval to proceed")
    print("got: " + answer)

start(approver)
print(approver.status)
resume(approver, "yes")
print(approver.status)
```

```txt theme={null}
preparing request...
paused
got: yes
completed
```

## 4. `ask_human` — the same thing, one call

`ask_human(question)` is `pause(question)` under a friendlier name for
the common case — asking a person something and waiting for their answer:

```sns theme={null}
agent approver:
    answer = ask_human("approve the $500 refund? (yes/no)")
    if answer == "yes":
        print("refund approved")
    else:
        print("refund declined")

start(approver)
print(approver.pause_reason)
resume(approver, "yes")
```

```txt theme={null}
approve the $500 refund? (yes/no)
refund approved
```

In a real system, `resume(approver, answer)` is the call your UI or Slack
bot makes once the actual human replies — this program supplies `"yes"`
directly so it stays runnable non-interactively.

## What you built

* `agent name: ...` — declares, doesn't run; `start(agent)` runs the body
* `.status` — `created` → `running` → `paused`/`completed`/`failed`
* `pause(reason?)` / `resume(agent, value?)` — genuine mid-body suspension, not polling
* `ask_human(question)` — `pause()` under the name that matches what it's for

## Next

<CardGroup cols={2}>
  <Card title="Agents" icon="robot" href="/ai-native/agents">
    The full reference — `async agent`, concurrency, agent state.
  </Card>

  <Card title="Pause & Resume" icon="pause" href="/ai-native/pause-resume">
    More patterns: approval gates, multi-step human review.
  </Card>

  <Card title="Safe Actions" icon="shield-check" href="/tutorials/safe-actions">
    Previous tutorial, if you missed it.
  </Card>

  <Card title="Which keyword do I want?" icon="list-check" href="/reference/keywords#which-keyword-do-i-want">
    `def` vs `tool` vs `action` vs `agent`, decided in one glance.
  </Card>
</CardGroup>
