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

# Where your code runs

> Actors, runner jobs, off-chain functions and workloads, and when to use each

A Cowboy app can run in more than one place, and this page helps you choose where each part goes.

Start with an actor, which holds the rules, records and money. When it needs a model, web API or tool, it starts a runner job. For heavy computation or a library, it calls an off-chain function. Anything that must stay running at a URL is a workload.

| Where | Use it for | What it costs |
| - | - | - |
| Actor | Rules, records, money | A fee per call |
| Runner job | A model, web API or tool | A price per job |
| Off-chain function | Computation, libraries | A price per call |
| Workload | A service at a URL | A deposit while it's running |

The caller pays an actor's call fee, and the actor's balance pays for its runner jobs and off-chain calls.

## Actors

An actor is a Python class that holds state and money. Every handler must give the same result wherever it runs, so an actor doesn't reach the network or its files itself: runners do that for it. [Build your first actor](https://docs.cowboy.inc/developers/your-first-actor.md) builds one.

## Runner jobs

A runner job is one call to a model, a web API or an MCP tool, made on the actor's behalf by a **runner**, a machine that does work for actors. To use one, write the handler as `async def` and `await` the job:

```python theme={"system"}
from cowboy_sdk import Actor, public, runner


class Asker(Actor):
    @public
    async def ask(self, question: str) -> None:
        result = await runner.llm(question, max_tokens=256)
        self.storage["answer"] = result.text
```

The handler continues when the answer arrives. You can try it without a model:

```bash theme={"system"}
cowboy run --handler ask --payload-json '"What is 2+2?"' --stub-llm '"4"'
```

```text Output theme={"system"}
(no return value)
State:
  …
  answer: 0x6134 (text "a4" or CBOR "4")
Off-chain calls:
  runner.llm -> stub ok
```

`--stub-llm` stands in for the model, and the state the run prints has `answer` set to `4`.

Web and tool calls need the `http.fetch` permission at deploy, naming the hosts they may reach ([Deploy it with web access](https://docs.cowboy.inc/developers/submitting-jobs.md#5-deploy-it-with-web-access)). [Call models, the web and tools](https://docs.cowboy.inc/developers/submitting-jobs.md) covers the rest.

## Off-chain functions

An off-chain function is your own code, run by a runner in a container, one call at a time. It can use any library, which makes it the place for work a handler can't do. To add one to a project:

```bash theme={"system"}
cowboy init fn --offchain
```

```text Output theme={"system"}
✓ Project initialized.
→ Preparing Python environment
✓ Python environment ready · .venv (0.2s)
→ Preparing off-chain environment
✓ Off-chain environment ready · .cowboy/local/offchain-env (0.1s)

Yeehaw! Project ready: /path/to/project
```

That adds an actor, `actors/fn/main.py`, and a starter Python function in `offchain/`. The actor imports it and calls it like any async function:

```python theme={"system"}
from cowboy_sdk import Actor, OffchainError, public

from offchain import count_primes


class FnActor(Actor):
    @public
    async def compute(self, limit: object) -> int | str:
        if isinstance(limit, bool) or not isinstance(limit, int):
            return "limit must be an integer"
        if not 0 <= limit <= 100_000:
            return "limit must be between 0 and 100000"
        try:
            result = await count_primes(limit)
        except OffchainError as failure:
            return str(failure)
        return result
```

`--offchain-runtime node` writes a Node function instead. `cowboy check` shows how one call is priced, and you can try a call on your machine with `cowboy run fn --handler compute --payload-json 100`.

## Workloads

A workload is a long-running service that an actor owns, reachable at a URL. You can write it in Node, Python or Rust. To add one to a project:

```bash theme={"system"}
cowboy init api --workload --runtime node
```

```text Output theme={"system"}
✓ Project initialized.
→ Preparing Python environment
✓ Python environment ready · .venv (0.2s)

Yeehaw! Project ready: /path/to/project

Check   cowboy check
Deploy  cowboy deploy api
```

That adds a folder for your service, an actor that owns it, and a `[workloads.api]` entry. [Run a web app or service](https://docs.cowboy.inc/developers/ship-a-web-app.md) goes on from there.

## Combine them

One app often uses several of these. An actor might hold the records and the money, a runner job ask a model, and a workload serve a web page. [Example actors](https://docs.cowboy.inc/developers/examples.md) shows this in practice.

## Next

* [Build your first actor](https://docs.cowboy.inc/developers/your-first-actor.md)
* [Call models, the web and tools](https://docs.cowboy.inc/developers/submitting-jobs.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.