Skip to main content

Overview

This tutorial walks through the full development loop for a Cowboy Actor: scaffold a project, write a counter actor with the cowboy_sdk Python library, unit-test it off-chain, deploy it to devnet, and call it from the CLI. The Quickstart deploys a starter actor; this tutorial is about writing your own. This page assumes the cowboy CLI is on your PATH and your project has already been initialized with cowboy init dev or another configured network. What you’ll learn:
  • The shape of an SDK actor: @actor, handlers, self.storage
  • Handler modes (@pure vs @deferred) and permissions (@public)
  • How to unit-test an actor before deploying it
  • The deploy → execute → inspect → iterate loop

1. Scaffold a project

This creates a .cowboy/ directory with a devnet wallet and network config (see cowboy init). Create a directory for your actor:

2. Write the actor

Create actors/counter/main.py:

What each piece does

The init handler runs once at deploy time (the deploy flow invokes the handler named init by default). It is a normal handler, not Python’s __init__.

Determinism rules you’ll hit first

Actor code must be deterministic — every validator replays it and must get identical results. The SDK ships replacements for the usual suspects:
  • import time is forbidden → use runtime.get_block_height() / runtime.get_timestamp_ms() (block-derived time)
  • import random is forbidden → use runtime.randomness(domain) (protocol randomness)
  • pickle is forbidden → use cowboy_sdk.codec (CBOR)
  • set() iteration order is not deterministic — prefer cowboy_sdk.ordered_set when you iterate over a set
See Determinism & Sandbox for the full list.

3. Test it off-chain

The SDK includes SimulatedChain, an in-memory harness that stubs the PVM host so handlers run as plain Python. Create actors/counter/test_counter.py:
Run it with pytest. Make sure the cowboy_sdk package is available in your Python test environment. Do not add the PVM’s full Python standard library to PYTHONPATH; it can shadow CPython’s stdlib and break pytest:
For the full testing toolkit — mocking cross-actor calls, advancing blocks to fire timers, state snapshots — see Testing Actors.

4. Deploy

The salt is a hex string (up to 32 bytes) that lets you deploy the same code to distinct addresses. You’ll get a transaction hash and a deterministic actor address (derived from your address, the code, and the salt — compute it ahead of time with cowboy actor address). Save it:

5. Call it

Inspect the actor and its events:
You should see your counter.incremented events in the logs.

6. Iterate

Edit main.py, re-run the tests, and redeploy. Deploying with a new salt (e.g. --salt 0x02) gives you a fresh actor at a new address; to upgrade the code at an existing address, see cowboy upgrade-actor. A natural next step: schedule the counter to increment itself. Actors can register block-height timers with runtime.schedule_timer(...) and handle the later callback in an on_timer handler — see the Scheduler overview, or the timer example if you are working from a Cowboy source checkout.

Next steps

Testing Actors

SimulatedChain, CallMock, and determinism checks in depth

Submitting Jobs to Runners

Call LLMs, HTTP APIs, and MCP tools from your actor

Working with Tokens

Create and move CIP-20 fungible tokens from actors and the CLI

SDK Overview

The full cowboy_sdk surface: models, continuations, guards