> ## Documentation Index
> Fetch the complete documentation index at: https://motiadev-add-real-system-tutorial-round-2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Scaffold a cross-language project, compose Python and TypeScript workers, and incrementally add functionality to a live system with zero downtime.

In this tutorial you will learn how iii makes it unreasonably simple to build and extend systems.

<Frame>
  <video controls playsInline preload="metadata" src="https://assets.motia.dev/videos/mp4/site/v1/iii-intro.mp4" />
</Frame>

<Info title="Install iii before proceeding">
  Make sure you have installed iii before proceeding. If you haven't then visit the
  [Install](./install) guide first.
</Info>

<Note>
  The Quickstart is a barebones tutorial intended to be completed within minutes. If you are more
  interested in learning and exploring the full power of iii then visit our [real world
  tutorial](./tutorials/linkly/overview).
</Note>

## 1. Create the project

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii project init quickstart --template quickstart
cd quickstart
```

This creates the two workers that you'll run: a Python worker that adds two numbers and stores the
sum in state, and a TypeScript worker that exposes an http endpoint and calls the Python worker
through the iii engine.

```
workers/
  math-worker/
    math_worker.py      # Python worker
  caller-worker/
    src/worker.ts       # TypeScript worker
```

## 2. Start the engine

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii --config config.yaml
```

The engine is now listening on `ws://localhost:49134`. Keep this terminal open and open a second
terminal in the `quickstart` directory for the remaining commands.

## 3. Start the Python worker

<Info title="Workers can run anywhere">
  Workers only need a WebSocket connection to the iii engine. They can run locally, in the cloud,
  replicated in kubernetes, or anywhere else.
</Info>

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii worker add ./workers/math-worker
```

You should see:

```
✓ Worker math-worker added to config.yaml
Path  /Users/tony/iii/projects/testing/quickstart/workers/math-worker
✓ Using cached deps (use --force to reinstall)
✓ math-worker started (pid: 12345)
✓ Worker auto-started
```

This worker registered the function `math::add` with the engine. You could call this function right
now using the command below.

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii trigger math::add a=2 b=3
```

However this is not much different than running an equivalent script on its own. The utility of iii
comes from being able to place any functionality into a worker and then compose that worker with
other workers through the engine, regardless of where each one runs or what language it's written
in.

<Tip>
  Workers need a moment to install their runtime dependencies after being added. If you see
  `"message": "Function math::add not found"`, wait a few seconds and try again.
</Tip>

## 4. Start the TypeScript worker

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii worker add ./workers/caller-worker
```

You should see:

```
✓ Worker caller-worker added to config.yaml
Path  /Users/tony/iii/projects/testing/quickstart/workers/caller-worker
✓ Using cached deps (use --force to reinstall)
✓ caller-worker started (pid: 23456)
✓ Worker auto-started
```

This worker registered the function `math::add_two_numbers` with the engine.

## 5. Call across languages

Call the TypeScript worker. It will call the Python worker through the engine and return the result:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii trigger math::add_two_numbers a=10 b=20
```

```json theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
{ "c": 30 }
```

## 6. Add state

The `iii worker add` command incrementally adds workers from the registry to your running system.
Start by adding the state worker, which gives every function access to a persistent key-value store.

From the folder containing iii's `config.yaml` run:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii worker add iii-state
```

Now open `workers/math-worker/math_worker.py` in your code editor and uncomment the state block so
the handler looks like this:

```python theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
def add_handler(payload: dict) -> dict:
    a = payload.get("a", 0)
    b = payload.get("b", 0)
    logger.info(f"math::add called in Python with a={a}, b={b}")
    result = {"c": a + b}

    running_total = worker.trigger(
        {
            "function_id": "state::get",
            "payload": {"scope": "math", "key": "running_total"},
        }
    )
    new_total = (running_total or 0) + result["c"]
    worker.trigger(
        {
            "function_id": "state::set",
            "payload": {"scope": "math", "key": "running_total", "value": new_total},
        }
    )
    result["running_total"] = new_total

    return result
```

Save the file and call the function a few times:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii trigger math::add a=2 b=3
```

```json theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
{ "c": 5, "running_total": 5 }
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii trigger math::add a=10 b=20
```

```json theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
{ "c": 30, "running_total": 35 }
```

The running total persists across every call, including calls that arrive through
`math::add_two_numbers`.

## 7. Add HTTP endpoints

Now let's add an HTTP worker to expose your functions as REST endpoints.

From the folder containing iii's `config.yaml` run:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
iii worker add iii-http
```

Open `workers/caller-worker/src/worker.ts` and uncomment the HTTP block at the bottom of the file:

```typescript theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
worker.registerFunction(
  "http::add_two_numbers",
  async (payload: { body: { a: number; b: number } }) => {
    const result = await worker.trigger({
      function_id: "math::add_two_numbers",
      payload: payload.body,
    });
    return {
      status_code: 200,
      body: { c: result.c, running_total: result.running_total },
      headers: { "Content-Type": "application/json" },
    };
  },
);

worker.registerTrigger({
  type: "http",
  function_id: "http::add_two_numbers",
  config: { api_path: "/math/add-two-numbers", http_method: "POST" },
});
```

Save the file, then call the new endpoint with curl:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
curl -X POST http://localhost:3111/math/add-two-numbers \
  -H 'Content-Type: application/json' \
  -d '{"a": 100, "b": 200}'
```

```json theme={"theme":{"light":"catppuccin-latte","dark":"dark-plus"}}
{ "c": 300, "running_total": 335 }
```

The same functions that respond to `iii trigger` now also respond to HTTP requests with no code
changes to the handlers themselves.

## How it works

For a walkthrough of how the engine, workers, functions, and triggers in this scaffold fit together,
see [Understanding iii](./understanding-iii). It uses this project as the worked example.

<Tip title="Inspect what's running">
  Open the iii Console with `iii console` in a new terminal: an interactive UI for workers,
  functions, triggers, logs, traces, and state. See the full [Console
  documentation](./using-iii/console) for details.
</Tip>

## Next Steps

You scaffolded a project, started two workers in different languages, called functions across them,
added persistent state, and exposed everything over HTTP, all by incrementally adding workers to a
running system.

<CardGroup cols={2}>
  <Card title="Real-world tutorial" href="./tutorials/linkly/overview" icon="graduation-cap">
    Go beyond the basics and explore the full power of iii by building a real-world application.
  </Card>

  <Card title="Use iii" href="./using-iii" icon="table-layout">
    Learn how to use iii in production.
  </Card>

  <Card title="Understanding iii" href="./understanding-iii" icon="table-layout">
    Understand functions, triggers, and workers from a conceptual point of view.
  </Card>
</CardGroup>
