API Reference
The Tinytown Rust API for programmatic control.
Quick Links
- Townhall REST API — HTTP control plane daemon
- Townhall MCP Server — MCP tools/resources/prompts
- Full rustdoc — Complete API documentation
Core Types
Town
#![allow(unused)]
fn main() {
use tinytown::Town;
// Initialize new town
let town = Town::init("./path", "name").await?;
// Connect to existing
let town = Town::connect("./path").await?;
// Operations
let agent = town.spawn_agent("name", "cli").await?;
let agent = town.agent("name").await?;
let agents = town.list_agents().await;
let channel = town.channel();
let config = town.config();
let root = town.root();
}
Agent
#![allow(unused)]
fn main() {
use tinytown::{Agent, AgentId, AgentType, AgentState};
// Create agent
let agent = Agent::new("name", "cli", AgentType::Worker);
// Supervisor (well-known ID)
let supervisor = Agent::supervisor("coordinator");
// Check state
if agent.state.is_terminal() { /* stopped or error */ }
if agent.state.can_accept_work() { /* idle */ }
}
AgentHandle
#![allow(unused)]
fn main() {
// Get handle from town
let handle = town.spawn_agent("worker", "claude").await?;
// Operations
let id = handle.id();
let task_id = handle.assign(task).await?;
handle.send(MessageType::StatusRequest).await?;
let len = handle.inbox_len().await?;
let state = handle.state().await?;
handle.wait().await?;
}
Task
#![allow(unused)]
fn main() {
use tinytown::{Task, TaskId, TaskState};
// Create
let task = Task::new("description");
let task = Task::new("desc").with_tags(["tag1", "tag2"]);
let task = Task::new("desc").with_parent(parent_id);
// Lifecycle
task.assign(agent_id);
task.start();
task.complete("result");
task.fail("error");
// Check state
if task.state.is_terminal() { /* completed, failed, or cancelled */ }
}
Message
#![allow(unused)]
fn main() {
use tinytown::{Message, MessageId, MessageType, Priority};
// Create
let msg = Message::new(from, to, MessageType::TaskAssign {
task_id: "abc".into()
});
// With options
let msg = msg.with_priority(Priority::Urgent);
let msg = msg.with_correlation(other_msg.id);
}
MessageType
#![allow(unused)]
fn main() {
pub enum MessageType {
// Semantic types for inter-agent communication
Task { description: String },
Query { question: String },
Informational { summary: String },
Confirmation { ack_type: ConfirmationType },
// Task lifecycle
TaskAssign { task_id: String },
TaskDone { task_id: String, result: String },
TaskFailed { task_id: String, error: String },
// Status
StatusRequest,
StatusResponse { state: String, current_task: Option<String> },
// Lifecycle
Ping,
Pong,
Shutdown,
// Extensibility
Custom { kind: String, payload: String },
}
pub enum ConfirmationType {
Received,
Acknowledged,
Thanks,
Approved,
Rejected { reason: String },
}
}
Helpers: msg.is_actionable(), msg.is_informational_or_confirmation()
Channel
#![allow(unused)]
fn main() {
use tinytown::Channel;
use std::time::Duration;
let channel = town.channel();
// Messages
channel.send(&msg).await?;
let msg = channel.receive(agent_id, Duration::from_secs(30)).await?;
let msg = channel.try_receive(agent_id).await?;
let len = channel.inbox_len(agent_id).await?;
channel.broadcast(&msg).await?;
// State
channel.set_agent_state(&agent).await?;
let agent = channel.get_agent_state(agent_id).await?;
channel.set_task(&task).await?;
let task = channel.get_task(task_id).await?;
}
Error Handling
#![allow(unused)]
fn main() {
use tinytown::{Error, Result};
match result {
Ok(value) => { /* success */ }
Err(Error::Redis(e)) => { /* redis error */ }
Err(Error::AgentNotFound(name)) => { /* agent missing */ }
Err(Error::TaskNotFound(id)) => { /* task missing */ }
Err(Error::NotInitialized(path)) => { /* town not init */ }
Err(Error::RedisNotInstalled) => { /* redis missing */ }
Err(Error::RedisVersionTooOld(ver)) => { /* upgrade redis */ }
Err(Error::Timeout(msg)) => { /* operation timed out */ }
Err(e) => { /* other error */ }
}
}
Example: Complete Workflow
use tinytown::{Town, Task, AgentState, Result};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<()> {
// Connect
let town = Town::connect(".").await?;
// Spawn agents
let dev = town.spawn_agent("dev", "claude").await?;
let reviewer = town.spawn_agent("reviewer", "codex").await?;
// Assign work
dev.assign(Task::new("Build the feature")).await?;
// Wait for completion
loop {
if let Some(agent) = dev.state().await? {
if matches!(agent.state, AgentState::Idle) {
break;
}
}
tokio::time::sleep(Duration::from_secs(5)).await;
}
// Send for review
reviewer.assign(Task::new("Review the feature")).await?;
Ok(())
}