# Agents and runs
An agent is a saved set of steps that works on your data, on a schedule or when something happens. Every agent belongs to a project. New to agents? Start with [Create an agent](/docs/agents/create-an-agent).
## Before you start [#before-you-start]
- You have the **project ID** of the project the agent lives in, and you can edit that project.
- Taking an agent live needs a workspace owner or admin, because a live agent spends credits.
- Every example assumes `nexus = Nexus.connect()`.
## Find agents [#find-agents]
```python
for agent in nexus.agents.list(project_id):
print(agent)
for agent in nexus.agents.list_all(): # every project you can open
print(agent)
```
## Save and test a draft [#save-and-test-a-draft]
An agent is a file `agents/.yaml` with its Python code in `agents//`, inside your project's code. `save()` stores both from a local folder as a draft:
```python title="test_agent.py"
from pathlib import Path
from klarety import KlaretyError, Nexus
PROJECT = "your-project-id"
with Nexus.connect() as nexus:
try:
version_id = nexus.agents.save(PROJECT, "daily-summary", root=Path("."))
run_id = nexus.agents.start(PROJECT, "daily-summary", draft=True, inputs={"days": 1})
except KlaretyError as failed:
raise SystemExit(f"Could not test the agent: {failed}")
print("Draft", version_id, "running as", run_id)
```
`nexus.agents.check(project_id, text)` checks the YAML text without saving it. A draft never runs on its own; `start(..., draft=True)` runs it once.
## Take it live [#take-it-live]
```python
nexus.agents.ask_to_publish(PROJECT, "daily-summary", version_id)
```
A person decides in the app. An owner or admin can publish directly with `nexus.agents.publish(PROJECT, "daily-summary", version_id)`; anyone else is refused. `unpublish()` takes it offline, and `publish()` with an earlier `version_id` brings that version back. `nexus.agents.version(project_id, version_id)` shows a saved version.
## Start a run and follow it [#start-a-run-and-follow-it]
Each run reports its state and steps:
```python title="run_and_wait.py"
import time
from klarety import Nexus
PROJECT = "your-project-id"
with Nexus.connect() as nexus:
run_id = nexus.agents.start(PROJECT, "daily-summary")
run = nexus.agents.run(PROJECT, run_id)
while run["state"] == "running":
time.sleep(10)
run = nexus.agents.run(PROJECT, run_id)
print(run["state"], run["reason"], run["credits"], "credits")
for step in run["steps"]:
print(step["id"], step["state"], step["reason"])
```
A run ends as `done`, `failed`, `declined` or `stopped`. Each step has its own state: `waiting`, `running`, `asking`, `done`, `failed`, `declined`, `stopped` or `skipped`, among others.
## Answer an approval step [#answer-an-approval-step]
A step in the `asking` state waits for a person to say yes:
```python
for step in run["steps"]:
if step["state"] == "asking":
nexus.agents.answer(PROJECT, run_id, step["id"], yes=True)
```
`yes=True` continues the run. `yes=False` stops it at that step.
## Read what a run produced [#read-what-a-run-produced]
```python
result = nexus.agents.result(PROJECT, run_id)
print(result["value"]) # up to 1 MiB
print(result["files"]) # files the run left
names = nexus.agents.outputs(PROJECT, run_id, step_id)
data = nexus.agents.output(PROJECT, run_id, step_id, names[0]) # bytes
print(nexus.agents.log(PROJECT, run_id, step_id))
```
For a step that runs once per item, pass `item=` to `outputs()`, `output()` and `log()` to read one item.
## List runs, stop and rerun [#list-runs-stop-and-rerun]
```python
for one in nexus.agents.runs(PROJECT, agent="daily-summary"): # newest first, page by page
print(one["run_id"], one["state"])
nexus.agents.stop(PROJECT, run_id)
new_run = nexus.agents.rerun(PROJECT, run_id, from_step="summarise")
print(nexus.agents.stats(PROJECT, days=7)) # runs per day: count, outcomes, cost
```
`rerun()` starts a new run from one step, reusing earlier steps' output. To page from another process, use `runs_page()` and pass its `next` back as `after`.
## Delete an agent [#delete-an-agent]
```python
nexus.agents.delete(PROJECT, "daily-summary")
```
The agent is paused and removed from the list. Its runs stay on record.
## What can go wrong [#what-can-go-wrong]
| Exception | Cause | What to do |
| --- | --- | --- |
| `KlaretyError: agents/.yaml does not exist` | `save()` could not find the file under `root`. | Run from the project's folder or pass `root=`. |
| `RefusedError` | You cannot edit the project, or you are not an admin and tried to `publish()`. | Use `ask_to_publish()`, or ask for access. |
| `NotFoundError` | No such project, agent or run. | Check the IDs. |
| `InsufficientCreditsError` | The workspace cannot pay for the run. | Add credits. |
## Next steps [#next-steps]
- [Try, go live and pause](/docs/agents/go-live) for the same steps in the app.
- [CLI](/docs/developers/cli) for `klarety agent` commands.
- [Jobs and batch jobs](/docs/developers/jobs) for background work without an agent.