arweave-ao-cookbook

Build decentralized applications on AO - a permanent, decentralized compute platform using actor model for parallel processes with native message-passing and permanent storage on Arweave

$ インストール

git clone https://github.com/enuno/claude-command-and-control /tmp/claude-command-and-control && cp -r /tmp/claude-command-and-control/INTEGRATION/processed/arweave-ao-cookbook-2025-12-26 ~/.claude/skills/claude-command-and-control

// tip: Run this command in your terminal to install the skill


name: arweave-ao-cookbook description: Build decentralized applications on AO - a permanent, decentralized compute platform using actor model for parallel processes with native message-passing and permanent storage on Arweave version: 1.0.0 category: blockchain-development tags: [arweave, ao, decentralized-compute, smart-contracts, blockchain, lua, permanent-storage, distributed-systems] source: https://cookbook_ao.arweave.net/ author: AO Community last_updated: 2025-12-26

AO Cookbook Skill

Purpose

Master building decentralized applications on AO - a revolutionary decentralized compute system where countless parallel processes interact within a single, cohesive environment. AO combines permanent storage on Arweave with actor model architecture to create truly decentralized, permanently available compute.

What is AO?

AO is a decentralized compute system built on the AO-Core protocol that employs the actor model (inspired by Erlang), enabling independent process operation through native message-passing mechanisms. Each process is an independent server in the network, communicating through messages stored permanently on Arweave.

HyperBEAM is the current production network, delivering:

  • High-performance message processing
  • Instant HTTP access to process state
  • Trustless, permissionless infrastructure
  • Permanent availability

Key Differentiator: Unlike traditional blockchains or cloud platforms, AO provides "your personal server in the AO computer" - a genuinely decentralized alternative to traditional hosting with permanent message storage.

When to Use This Skill

Perfect for:

  • Building decentralized applications requiring permanent storage
  • Creating smart contracts with complex state and interactions
  • Developing chatbots, games, and interactive applications on blockchain
  • Implementing token systems, voting mechanisms, and governance
  • Building systems that require trustless, permanent compute
  • Creating applications that benefit from parallel process execution
  • Developing Arweave-integrated applications

Not ideal for:

  • Simple static websites (use traditional hosting)
  • Applications requiring real-time sub-millisecond latency
  • Systems that need to delete or modify historical data
  • Traditional centralized database applications
  • Projects without permanent storage requirements

Core Concepts

1. Processes

Independent servers in the decentralized AO network. Each process:

  • Has its own state and memory
  • Executes autonomously
  • Communicates via messages
  • Persists permanently on Arweave
  • Can spawn other processes

2. Messages

The core communication mechanism between processes:

  • Permanently stored on Arweave
  • Asynchronous by nature
  • Contain data and metadata
  • Trigger handler functions
  • Enable process interaction

3. Handlers

Event processors that respond to incoming messages:

  • Pattern-match on message properties
  • Execute logic based on message content
  • Update process state
  • Send responses to other processes
  • Enable reactive programming model

4. aos (AO Shell)

Interactive development environment:

  • Command-line interface for AO processes
  • Built-in Lua REPL
  • Supports modules and blueprints
  • Enables rapid prototyping
  • Provides process management tools

5. Permanence

Everything is permanent on Arweave:

  • Messages never disappear
  • Code is immutable once deployed
  • State history is preserved
  • Audit trails are built-in
  • No centralized control

Installation & Setup

Prerequisites

  • NodeJS: Version 20 or higher
  • Code Editor: Any editor (VS Code recommended)
  • Arweave Wallet (optional): For custom wallet authentication

Step 1: Install AOS

# Install AOS globally via npm
npm i -g https://get_ao.arweave.net

# Verify installation
aos --version

Step 2: Connect to HyperBEAM Network

# Option 1: Connect to HyperBEAM for optimal performance
aos --node https://forward.computer

# Option 2: Use default settings
aos

# Option 3: Specify custom wallet
aos --wallet ~/.arweave-wallet.json

# Auto-generated wallet location
# Default: ~/.aos.json (created automatically if not specified)

Step 3: Verify Connection

-- In aos shell, try basic commands:
print("Hello AO")
-- Output: Hello AO

-- Check your process ID
Name
-- Output: Your process name

Owner
-- Output: Your wallet address

-- View inbox
#Inbox
-- Output: Number of unhandled messages

Basic Usage Patterns

Pattern 1: Simple State Management

-- Initialize state variable
counter = 0

-- Create handler for increment messages
Handlers.add(
  "increment",
  Handlers.utils.hasMatchingTag("Action", "Increment"),
  function(msg)
    counter = counter + 1
    print("Counter incremented to: " .. counter)

    -- Send response
    Send({
      Target = msg.From,
      Data = tostring(counter)
    })
  end
)

-- Access state via HTTP
-- https://forward.computer/<process-id>~process@1.0/compute/counter

Why this works: State persists permanently and is accessible via HTTP through HyperBEAM.

Pattern 2: Message Passing Between Processes

-- Send message to another process
Send({
  Target = "process-id-here",
  Action = "Chat-Message",
  Data = "Hello from my process!"
})

-- Handle incoming messages
Handlers.add(
  "chat",
  Handlers.utils.hasMatchingTag("Action", "Chat-Message"),
  function(msg)
    print("Received: " .. msg.Data)
    print("From: " .. msg.From)

    -- Reply to sender
    Send({
      Target = msg.From,
      Data = "Message received!"
    })
  end
)

Pattern: Asynchronous message-passing enables loosely-coupled process communication.

Pattern 3: Inbox Monitoring

-- Custom prompt showing inbox count
function Prompt()
  return "📬 Inbox: " .. #Inbox .. " > "
end

-- Check inbox
if #Inbox > 0 then
  -- Access first message
  local msg = Inbox[1]
  print("From: " .. msg.From)
  print("Data: " .. msg.Data)
end

Pattern: Monitor incoming messages in real-time with custom prompts.

Pattern 4: Using Modules

-- Load JSON module
local json = require("json")

-- Encode data
local data = { name = "Alice", balance = 1000 }
local encoded = json.encode(data)

-- Decode JSON
local decoded = json.decode(encoded)
print(decoded.name)  -- Output: Alice

-- Use .utils module for functional programming
local utils = require(".utils")
local numbers = {1, 2, 3, 4, 5}
local doubled = utils.map(function(n) return n * 2 end, numbers)
-- Result: {2, 4, 6, 8, 10}

Available Modules:

  • json: JSON encoding/decoding
  • ao: Core AO functions (Send, Spawn)
  • .base64: Base64 encoding/decoding
  • .pretty: Formatted output (tprint)
  • .utils: Functional utilities (map, reduce, filter)

Pattern 5: Multi-line Code with Editor Mode

-- Enter editor mode
.editor

-- Write multi-line function (type all lines, then Ctrl+D to execute)
function createToken(name, symbol, supply)
  return {
    Name = name,
    Symbol = symbol,
    TotalSupply = supply,
    Balances = {}
  }
end
-- Press Ctrl+D to exit editor mode

-- Use the function
myToken = createToken("MyToken", "MTK", 1000000)
print(myToken.Name)  -- Output: MyToken

Pattern 6: Loading External Lua Files

-- Load functions from file
.load myFunctions.lua

-- Functions from file are now available
-- (assuming myFunctions.lua defines functions)

Use case: Organize complex logic in files, load into aos session.

Common Workflows

Workflow 1: Building a Token System

-- Initialize token state
Token = {
  Name = "MyToken",
  Symbol = "MTK",
  TotalSupply = 1000000,
  Balances = {}
}

-- Initialize owner balance
Token.Balances[Owner] = Token.TotalSupply

-- Transfer handler
Handlers.add(
  "transfer",
  Handlers.utils.hasMatchingTag("Action", "Transfer"),
  function(msg)
    local recipient = msg.Tags.Recipient
    local amount = tonumber(msg.Tags.Amount)

    -- Validate sender has balance
    if Token.Balances[msg.From] >= amount then
      Token.Balances[msg.From] = Token.Balances[msg.From] - amount
      Token.Balances[recipient] = (Token.Balances[recipient] or 0) + amount

      Send({
        Target = msg.From,
        Data = "Transfer successful"
      })
    else
      Send({
        Target = msg.From,
        Data = "Insufficient balance"
      })
    end
  end
)

-- Balance query handler
Handlers.add(
  "balance",
  Handlers.utils.hasMatchingTag("Action", "Balance"),
  function(msg)
    local target = msg.Tags.Target or msg.From
    local balance = Token.Balances[target] or 0

    Send({
      Target = msg.From,
      Data = tostring(balance)
    })
  end
)

Workflow 2: Creating a Chatroom

-- Chatroom state
Chatroom = {
  Members = {},
  Messages = {}
}

-- Join handler
Handlers.add(
  "join",
  Handlers.utils.hasMatchingTag("Action", "Join"),
  function(msg)
    Chatroom.Members[msg.From] = true

    -- Notify all members
    for member, _ in pairs(Chatroom.Members) do
      Send({
        Target = member,
        Action = "Notification",
        Data = msg.Tags.Username .. " joined the chatroom"
      })
    end
  end
)

-- Send message handler
Handlers.add(
  "broadcast",
  Handlers.utils.hasMatchingTag("Action", "Broadcast"),
  function(msg)
    -- Store message
    table.insert(Chatroom.Messages, {
      From = msg.From,
      Text = msg.Data,
      Timestamp = msg.Timestamp
    })

    -- Broadcast to all members
    for member, _ in pairs(Chatroom.Members) do
      if member ~= msg.From then
        Send({
          Target = member,
          Action = "ChatMessage",
          From = msg.From,
          Data = msg.Data
        })
      end
    end
  end
)

Workflow 3: Spawning New Processes

-- Spawn a new process
Send({
  Target = ao.id,  -- ao core process
  Action = "Eval",
  Data = [[
    -- Code for new process
    Handlers.add(
      "ping",
      Handlers.utils.hasMatchingTag("Action", "Ping"),
      function(msg)
        Send({ Target = msg.From, Data = "Pong!" })
      end
    )
  ]]
})

-- Programmatic spawn with Spawn()
local newProcess = Spawn("module-id", {
  Data = "Initial state",
  Tags = {
    Name = "SubProcess",
    Type = "Worker"
  }
})

Workflow 4: Using Blueprints

Available blueprint templates:

  • chatroom: Complete chatroom implementation
  • token: Token standard with transfer/balance
  • voting: Voting mechanism with proposals
  • staking: Token staking with rewards
  • CRED: Reputation/credit system
-- Load blueprint (example - actual syntax may vary)
-- Blueprints provide pre-built handlers and state management

Advanced Patterns

Pattern: State Persistence & HTTP Access

-- Define state that should be HTTP accessible
GameState = {
  players = {},
  score = 0,
  round = 1
}

-- State is automatically accessible via HTTP
-- GET https://forward.computer/<process-id>~process@1.0/compute/GameState
-- Returns JSON representation of GameState

Power: Any process variable becomes instantly queryable via HTTP through HyperBEAM.

Pattern: Handler Composition

-- Helper function for common checks
local function isAuthorized(msg)
  return msg.From == Owner
end

-- Composed handler with authorization
Handlers.add(
  "admin-action",
  function(msg)
    return Handlers.utils.hasMatchingTag("Action", "Admin")(msg)
      and isAuthorized(msg)
  end,
  function(msg)
    -- Admin logic here
    print("Admin action executed")
  end
)

Pattern: Error Handling

Handlers.add(
  "safe-operation",
  Handlers.utils.hasMatchingTag("Action", "SafeOp"),
  function(msg)
    local success, result = pcall(function()
      -- Potentially error-prone operation
      local value = tonumber(msg.Tags.Amount)
      assert(value > 0, "Amount must be positive")
      return value * 2
    end)

    if success then
      Send({
        Target = msg.From,
        Data = tostring(result)
      })
    else
      Send({
        Target = msg.From,
        Error = result  -- Contains error message
      })
    end
  end
)

Troubleshooting

Issue: "aos command not found"

Solution:

# Verify NodeJS version
node --version  # Should be v20+

# Reinstall aos
npm i -g https://get_ao.arweave.net

# Check PATH
echo $PATH | grep npm

Issue: Connection timeout

Solution:

# Try different node
aos --node https://forward.computer

# Check network connection
curl https://forward.computer

# Verify wallet if using custom
aos --wallet ~/.arweave-wallet.json

Issue: "Handler not triggering"

Solutions:

  1. Check tag matching:

    -- Verify message has correct tags
    print(msg.Tags.Action)  -- Should match your matcher
    
  2. Test handler directly:

    -- Simulate message
    local testMsg = {
      From = "test-id",
      Tags = { Action = "Test" },
      Data = "test data"
    }
    -- Call handler function manually
    
  3. Check handler order:

    -- List all handlers
    Handlers.list()
    -- Handlers execute in order, first match wins
    

Issue: State not persisting

Explanation: State in aos session is temporary until messages are sent/processed. To persist:

  1. Send messages to your process (triggers permanent storage)
  2. Deploy handlers as permanent code
  3. Use .load to reload functions across sessions

Issue: "Inbox full" or performance degradation

Solution:

-- Process and clear inbox
for i = 1, #Inbox do
  local msg = Inbox[i]
  -- Handle message
  print("Processing: " .. msg.From)
end

-- Inbox clears automatically after handlers process messages

CLI Reference

aos Command-Line Options

aos [options]

Options:
  --wallet <path>       Path to Arweave wallet (default: ~/.aos.json)
  --node <url>          AO node URL (default: https://forward.computer)
  --module <id>         Module ID for process
  --cron <interval>     Cron interval for process
  --version             Show version
  --help                Show help

aos Shell Commands

CommandPurposeExample
.editorEnter multi-line edit mode.editor then Ctrl+D to execute
.load <file>Load Lua file.load functions.lua
.exitExit aos shell.exit
#InboxCount unhandled messagesprint(#Inbox)
Inbox[n]Access message at indexlocal msg = Inbox[1]

Global Functions & Variables

GlobalTypePurpose
Send(msg)FunctionSend message to process
Spawn(module, msg)FunctionCreate new process
InboxTableUnhandled messages
HandlersModuleHandler management
OwnerStringProcess owner address
NameStringProcess name

Best Practices

1. Handler Organization

-- Group related handlers
-- Authentication handlers
Handlers.add("auth:login", ...)
Handlers.add("auth:logout", ...)

-- Business logic handlers
Handlers.add("game:move", ...)
Handlers.add("game:score", ...)

2. State Management

-- Use clear state structures
State = {
  users = {},
  config = {
    maxUsers = 100,
    timeout = 300
  },
  stats = {
    totalMessages = 0,
    activeUsers = 0
  }
}

-- Avoid global pollution
-- Use tables to organize

3. Error Handling

-- Always validate inputs
function validateAmount(amount)
  local num = tonumber(amount)
  assert(num, "Amount must be a number")
  assert(num > 0, "Amount must be positive")
  return num
end

-- Use pcall for risky operations
local success, result = pcall(validateAmount, msg.Tags.Amount)
if not success then
  Send({ Target = msg.From, Error = result })
  return
end

4. Testing Handlers

-- Create test utilities
function testHandler(handler, mockMsg)
  return pcall(function()
    handler(mockMsg)
  end)
end

-- Test before deploying
local testMsg = {
  From = "test-sender",
  Tags = { Action = "Transfer", Amount = "100" },
  Data = ""
}
local success, err = testHandler(transferHandler, testMsg)
print(success and "✓ Test passed" or "✗ Test failed: " .. err)

5. Documentation

--[[
  Handler: token:transfer
  Purpose: Transfer tokens between addresses
  Tags Required:
    - Action: "Transfer"
    - Recipient: target address
    - Amount: token amount (string number)
  Returns: Success/failure message
]]
Handlers.add("token:transfer", ...)

Resources

Official Documentation

Community

  • Discord: Community support and discussions
  • Tutorials: Begin track, Bots & Games, Advanced guides

Learning Paths

  1. Getting Started: Welcome → Installation → Basic messaging
  2. Token Development: Token tutorial → Transfer mechanics → Balance queries
  3. Game Development: Bots & Games track → State management → Multiplayer
  4. Advanced: Custom modules → Process spawning → HTTP integration

Examples Repository

See /examples directory for complete working examples:

  • chatroom.lua - Full chatroom implementation
  • token.lua - Token standard with all handlers
  • game.lua - Simple game with state management
  • voting.lua - Voting system with proposals

Version History

  • 1.0.0 (2025-12-26): Initial skill creation
    • Core concepts and patterns
    • Installation and setup
    • Basic and advanced workflows
    • Troubleshooting guide
    • CLI reference
    • Best practices

Last Updated: December 26, 2025 Source: https://cookbook_ao.arweave.net/ Community: AO Discord and GitHub Status: Production Ready ✅

Repository

enuno
enuno
Author
enuno/claude-command-and-control/INTEGRATION/processed/arweave-ao-cookbook-2025-12-26
3
Stars
0
Forks
Updated1w ago
Added1w ago