All integrations

Python SDK

ML training loops, Rake-style scripts, AI agents.

LiveSDKchirp login

The Python SDK is the primary integration path for long-running Python work - model training loops, scraping pipelines, batch jobs, AI agents. The `@track` decorator is one line above any function and gives you a Live Activity that starts when the function is entered, updates as you call `update()`, and ends green or red depending on whether the function returned or threw.

Two flavors are exported. `@track` is the simple decorator; `ChirpAgent` is a class for finer control - manual lifecycle, multiple updates, custom dismissal policy. Both rely on the same lightweight HTTP client (stdlib `urllib`, no third-party deps).

Prerequisites

  • Python ≥ 3.9.
  • Chirp installed on your phone, signed in.

Setup

  1. 1

    Install + authenticate

    chirp login is a one-time pairing - opens a browser, drops a token at ~/.chirprc. The SDK auto-discovers it. CI environments use CHIRP_API_KEY instead.

    shell
    pip install chirp-sdk
    chirp login
  2. 2

    Wrap a function with `@track`

    The simplest pattern. Decorate any function and Chirp owns its lifecycle: starts the activity on call, updates every time you log progress, ends green on return or red on exception. Works for sync and async functions.

    train.py
    from chirp import track, update
    
    @track("model training", theme="#818cf8")
    def train():
        for epoch in range(10):
            train_one_epoch()
            # Update fields as you go - only the keys you pass are touched.
            update(progress=(epoch + 1) / 10, status=f"Epoch {epoch + 1}/10")
    
    train()  # phone shows the Live Activity for the entire call
  3. 3

    Use `ChirpAgent` for fine-grained control

    When the function shape doesn't fit a decorator (e.g. you want to keep an activity alive across multiple top-level entry points, or branch the lifecycle yourself), open a context manager.

    python
    from chirp import ChirpAgent
    
    with ChirpAgent("data backfill", schema="@progress") as a:
        a.update(progress=0.1, metaLeft="reading source")
        rows = read_source()
        a.update(progress=0.5, metaLeft=f"{len(rows)} rows fetched")
        write_destination(rows)
        a.update(progress=1.0, metaLeft="done")
    # Auto-ends green on context exit, red if an exception escaped.
  4. 4

    Pick a schema that matches your workload

    The default schema is @progress (a generic 0-100% bar). If your job has a dollar cost (LLM inference), use @openrouter-spend. If it's a long GPU run, use @gpu-job. Browse the catalog at /templates for the full list. Pass schema="@<id>" to switch.

Async / asyncio

python
from chirp import track

@track("scrape", schema="@scrape-deep")
async def crawl(start_url):
    async for page in crawler(start_url):
        await update(pages=page.index, queue=page.queue_size)

import asyncio
asyncio.run(crawl("https://docs.example.com"))

What you’ll see

When `train()` is called, an @progress activity starts on your phone with the title "model training" and progress 0%. Each `update()` call refreshes the bar. When the function returns, the activity ends with a green checkmark; if it raises, the activity ends red with the exception type as the final status. Multiple concurrent decorated functions get their own activities.

Troubleshooting

I get `chirp.errors.NoCredentialsError: ~/.chirprc not found`.
Run chirp login once on the machine. In CI environments where you can't run that, set CHIRP_API_KEY instead - the SDK reads it as a fallback.
My activity ends red even though the function completed successfully.
Check the function isn't catching an exception silently. The decorator inspects what the wrapped function actually returned vs. threw - if you try/except inside, the SDK sees a clean return.
The lock screen card shows generic placeholders instead of my data.
Make sure the keys you pass to update() match the schema's bindings. @progress accepts progress (0-1), metaLeft, metaRight, trailing. Other schemas have different keys - see /templates.