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

# Core concepts

> The mental model behind Cycls: three layers, four builders, and three verbs.

Four ideas carry most of the SDK. Read them in order and the rest of the
reference makes sense on first pass.

## 1. Three layers

Each layer extends the one below it, so anything a Function can do an App can do,
and anything an App can do an Agent can do.

```mermaid theme={null}
flowchart TD
    A["@cycls.agent<br/>chat product, managed LLM loop, web UI"] --> B["@cycls.app<br/>blocking ASGI service, auth, per-user storage"]
    B --> C["@cycls.function<br/>containerized Python, volumes, schedules"]
```

| Layer                        | Input              | Output                       | Use it for                                      |
| ---------------------------- | ------------------ | ---------------------------- | ----------------------------------------------- |
| [Function](/build/functions) | function arguments | return value                 | batch jobs, APIs, scheduled work, heavy compute |
| [App](/build/apps)           | HTTP requests      | an ASGI app you return       | dashboards, internal tools, custom front ends   |
| [Agent](/agents/overview)    | `context`          | a stream of events you yield | chat products                                   |

## 2. Four builders

Configuration lives in fluent, immutable builders. Every method returns a new
object, so one base config can be branched safely.

```python theme={null}
base = cycls.Image().pip("httpx")

fast = base.pip("orjson")        # a new Image
slow = base.apt("ffmpeg")        # another new Image, `base` is unchanged
```

<CardGroup cols={2}>
  <Card title="cycls.Image" icon="box" href="/build/images">
    `.pip()` `.apt()` `.copy()` `.run()` `.rebuild()`
  </Card>

  <Card title="cycls.Web" icon="window" href="/web/interface">
    `.auth()` `.title()` `.brand()` `.analytics()` `.workspaces()`
  </Card>

  <Card title="cycls.LLM" icon="brain" href="/agents/models">
    `.model()` `.system()` `.tools()` `.allowed_tools()` `.price()`
  </Card>

  <Card title="cycls.Volume" icon="hard-drive" href="/build/volumes">
    `.read_only()` `.sub_path()`
  </Card>
</CardGroup>

Decorators accept exactly the builders they need, never loose keyword soup.

```python theme={null}
@cycls.function(image=..., volumes=..., schedule=..., cpu=..., memory=...)
@cycls.app(image=..., volumes=..., auth=...)
@cycls.agent(image=..., web=..., volumes=...)
```

## 3. Three verbs

The same three words work in Python and on the command line.

| Verb     | Where the code runs | Which code runs                |
| -------- | ------------------- | ------------------------------ |
| `run`    | your Docker         | the code you are holding       |
| `remote` | Cycls Cloud         | the code you are holding       |
| `deploy` | Cycls Cloud         | the code frozen at deploy time |

```python theme={null}
simulate.run(1000)        # local Docker
simulate.remote(1000)     # cloud, current code
simulate.deploy()         # cloud, frozen and named
```

```bash theme={null}
cycls run file.py            # local Docker, rerun on save
cycls run file.py --remote   # cloud, rerun on save
cycls deploy file.py         # freeze and publish
```

`f.remote()` is the development loop. `cycls.remote("name")` calls what was
deployed, from any machine that has your API key. Read
[Local and remote builds](/ship/builds) for what happens in each case.

## 4. Code travels as a pickle

Your function is serialized with cloudpickle, including closures and captured
variables, then executed inside a container built from your `Image`. Two rules
follow, and both are enforced for you:

* The container's Python matches your host's major and minor version.
* The container's cloudpickle matches your host's exact version.

<Warning>
  A function defined in the file you deploy travels by value. A function imported
  from another module travels by reference, so the container will try to import
  that module. If you split code across files, bundle them with
  `cycls.Image().copy("helpers.py")` so the import resolves.
</Warning>

## State lives on volumes

Containers are stateless. Anything that must survive a redeploy goes on a
[volume](/build/volumes), which is named storage attached at a mount path.

```python theme={null}
data = cycls.Volume("training-data")

@cycls.function(volumes={"/data": data})
def crunch(day):
    import pandas as pd
    return pd.read_parquet(f"/data/events-{day}.parquet").sum()
```

Agents keep chats, files and credentials under `/workspace`, so the decorator
requires a volume there:

```python theme={null}
@cycls.agent(volumes={"/workspace": cycls.Volume("my-agent")})
async def my_agent(context):
    ...
```

Deleting a deployment detaches its volumes and never deletes their data.

## Images are content addressed

Cycls hashes the image declaration, including the contents of copied files, into
a deterministic Docker tag. Identical inputs reuse the cached build everywhere.
Change one package and only that layer rebuilds.

## Next steps

<CardGroup cols={2}>
  <Card title="Agents" icon="comments" href="/agents/overview">
    The managed loop, the context object and the event stream.
  </Card>

  <Card title="Functions" icon="box" href="/build/functions">
    Run, remote, map, deploy and schedule.
  </Card>
</CardGroup>
