An older binary addressed a shard by org alone (<data>/<org>/<ns>.db). This one reads three levels down, so the first boot after the upgrade finds nothing, creates empty shards beside the full ones, enumerates zero tenants and never fires a schedule again — silently, with every byte still on disk one directory up. store.Upgrade inserts the two sentinel levels uniformly, including the old empty-org dir (_ -> _/_/_). A rename within one filesystem: no page rewritten, no re-encryption. Journals move before their database, so a run that stops half way never leaves a database without the WAL holding its last commits. Idempotent — a moved shard leaves nothing at its old path — so a deploy can run it unconditionally ahead of the daemon. Two refusals, both loud and both non-destructive: A master key is set. Pre-upgrade shards are plaintext and moving one does not encrypt it; the next boot would wrap a fresh DEK around a file it then failed to decrypt. Move first, encrypt second. A destination is occupied (ErrOccupied). The only way there is booting this binary before the move ran, which creates an EMPTY shard where the full one belongs — and anything started after that boot is in the empty one. Both files are kept, the other tenants still move, and the operator picks which is authoritative. upgrade and migrate stay separate axes: upgrade moves EVERY shard forward in time (layout), migrate moves ONE shard across space (nodes). Also: refuse a socket path over sockaddr_un.sun_path by name. The kernel answers "bind: invalid argument" and names neither the path nor the limit, and a socket under a deployment's data directory sits close to it. Co-authored-by: Hanzo Dev <[email protected]>
Introduction
Hanzo Tasks is a durable execution engine that powers AI agent orchestration in the Hanzo ecosystem. It enables developers to build scalable, fault-tolerant workflows that automatically handle intermittent failures and retry failed operations.
Tasks provides the backbone for:
- Playground spaces -- each space maps to a Tasks namespace
- Agent execution -- each agent runs as a Tasks worker
- Durable cron and batch jobs -- reliable scheduled and bulk operations
MIT licensed. See LICENSE.
Getting Started
Build
make tasksd
Run
./tasksd start
Or with a config file:
./tasksd --config-file config/development-sqlite.yaml --allow-no-auth start
Build from source
go build ./cmd/tasksd/
./tasksd start
Module
github.com/hanzoai/tasks
Integration
Hanzo Tasks integrates with the broader Hanzo ecosystem:
- Playground connects to the Tasks server via the durable-execution SDK
- Base embeds Tasks for durable cron/batch execution
- Each playground space = a Tasks namespace
- Each agent = a Tasks worker
Repository
This repository contains the source code of the Hanzo Tasks server.
The wire is luxfi/zap (binary, native, on _tasks._tcp:9999).
There is no gRPC and no go.temporal.io anywhere in the build.
To drive Tasks from Go, depend on pkg/sdk — the native
ZAP client. To embed the server in a Go process (e.g. a Hanzo Base
app), depend on pkg/tasks and call tasks.Embed().
Browser clients hit the JSON shim at /v1/tasks/* and the realtime
stream at /v1/tasks/events (Server-Sent Events). AI agents hit the
MCP surface at /v1/tasks/mcp (JSON-RPC 2.0).
Contributing
See CONTRIBUTING.md for development setup and guidelines.