dispatch

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: Apache-2.0

README

dispatch

Control plane for agent execution nodes: deploy one service, scale sandboxed agents with metrics on a shared workspace.

Download · Report Bug · Go Docs

CI   Go Reference   License

Beta. dispatch is pre-1.0 and under active development. Interfaces are stabilizing but may change between minor versions; queues are in-memory (at-most-once delivery) and the shared workspace backend is a local directory. Durable brokers and GCS/S3 workspace backends are on the roadmap.

Features

  • Deploy a single service and scale its agent execution nodes without changing it
  • Producer/consumer execution: tasks flow through a queue; scaling out is adding consumers, locally as goroutines or remotely as Kubernetes pods and serverless containers running dispatch work
  • Sandboxed tools: every tool is locked to declared workspace areas and spawn targets; anything not granted is denied, so a compromised tool cannot leak outside its area
  • NGAC access control: access is defined in a NIST-style policy machine (users, attributes, associations, prohibitions) and enforced by the sandbox; flat per-tool policies compile into the same graph, full access specs express group grants and overriding denials
  • Shared workspace: all nodes read and write one storage backend, so state lives in exactly one place
  • Self-referential agents: a tool can spawn sub-tasks back into its own deployment (an agent calling another agent), gated by its policy
  • Metrics built in: node counts, task throughput, and latency recorded behind a transport-agnostic interface
  • Orthogonal interfaces: workspace, sandbox, tool, queue, node, and control plane compose without knowing about each other

Installation

Script (macOS / Linux)

curl -fsSL https://raw.githubusercontent.com/urmzd/dispatch/main/install.sh | sh

Manual

Download a pre-built binary from the releases page.

Go SDK

go get github.com/urmzd/dispatch

Quick Start

Run the control plane and exercise it with the built-in sandboxed echo tool:

dispatch serve &

curl -X POST localhost:8484/v1/deployments \
  -d '{"name":"echo-service","replicas":3,"policies":[{"tool":"echo","areas":[{"prefix":"echo"}]}]}'

curl -X POST localhost:8484/v1/deployments/echo-service/tasks \
  -d '{"tool":"echo","input":"hello"}'

curl -X POST localhost:8484/v1/deployments/echo-service/scale -d '{"replicas":10}'

curl localhost:8484/metrics

Or compose the same thing in Go:

// Basic example: compose a control plane from the orthogonal pieces —
// a local workspace, a sandboxed tool, an in-process node factory, and an
// in-memory metrics recorder — then deploy a service, scale it out, submit
// tasks, and print the resulting metrics.
//
// Prerequisites: none. Run with:
//
//	go run ./examples/basic/
package main

import (
	"bytes"
	"context"
	"fmt"
	"log"
	"os"
	"sort"

	"github.com/urmzd/dispatch/pkg/controlplane"
	"github.com/urmzd/dispatch/pkg/metrics"
	"github.com/urmzd/dispatch/pkg/node/inproc"
	"github.com/urmzd/dispatch/pkg/sandbox"
	"github.com/urmzd/dispatch/pkg/task"
	"github.com/urmzd/dispatch/pkg/tool"
	"github.com/urmzd/dispatch/pkg/workspace"
)

func main() {
	ctx := context.Background()

	// Shared workspace: every node reads and writes the same backend.
	dir, err := os.MkdirTemp("", "dispatch-example-*")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(dir)
	ws, err := workspace.NewLocal(dir)
	if err != nil {
		log.Fatal(err)
	}

	// One tool. It sees only the workspace view its policy grants below.
	registry := tool.NewRegistry()
	err = registry.Register(tool.Func("greet", func(ctx context.Context, rt tool.Runtime, in []byte) ([]byte, error) {
		out := []byte("hello, " + string(in))
		// Allowed: "greetings/..." is inside this tool's area.
		if err := rt.Workspace().Write(ctx, "greetings/last", bytes.NewReader(out)); err != nil {
			return nil, err
		}
		// Denied by the sandbox: "secrets/..." is outside the area.
		if err := rt.Workspace().Write(ctx, "secrets/steal", bytes.NewReader(out)); err != nil {
			fmt.Printf("sandbox blocked the leak: %v\n", err)
		}
		return out, nil
	}))
	if err != nil {
		log.Fatal(err)
	}

	// Compose the control plane and deploy one service.
	rec := metrics.NewMemory()
	plane := controlplane.NewMemory(inproc.NewFactory(registry, ws), rec)
	err = plane.Deploy(ctx, controlplane.ServiceSpec{
		Name:     "greeter",
		Replicas: 1,
		Policies: []sandbox.Policy{{Tool: "greet", Areas: []sandbox.Area{{Prefix: "greetings"}}}},
	})
	if err != nil {
		log.Fatal(err)
	}

	// Scale out; submitted tasks are consumed by competing nodes.
	if err := plane.Scale(ctx, "greeter", 3); err != nil {
		log.Fatal(err)
	}
	for _, name := range []string{"ada", "grace", "alan"} {
		res, err := plane.Submit(ctx, "greeter", task.Task{Tool: "greet", Input: []byte(name)})
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%s ran on %s: %s\n", name, res.NodeID, res.Output)
	}

	// Metrics accumulated along the way.
	fmt.Println("\nmetrics:")
	snap := rec.Snapshot()
	keys := make([]string, 0, len(snap))
	for k := range snap {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Printf("  %s %g\n", k, snap[k])
	}
}

See examples/ for more.

Scaling on Kubernetes

Execution scales by replicating consumers, not by touching the control plane. The reference manifests deploy one dispatch serve service and a fleet of dispatch work pods that lease tasks from it over HTTP:

minikube start
eval $(minikube docker-env) && docker build -t dispatch:dev .
kubectl apply -f deploy/k8s/dispatch.yaml

kubectl scale deployment/dispatch-worker --replicas=10

Deploy a service with "replicas": -1 (no local nodes) and every task is executed by the worker fleet. An HPA on queue or task metrics gives the same effect for serverless-style autoscaling.

Examples

Example Description
basic Deploy, scale, submit, and observe with a sandboxed tool
ngac Define access as an NGAC policy graph: attribute grants, prohibitions, spawn objects
saige Run saige AI agents as workloads, including an agent spawning a sub-agent

Architecture

Tasks are produced onto per-deployment queues and executed by competing consumers. Each consumer is a node that resolves tools from a registry and confines every call through the deployment's NGAC policy graph: the executing tool is the policy-machine user, workspace keys and spawn targets are the objects, and the default is deny. The packages form a strict one-way dependency graph so each concern can change independently.

See docs/architecture/overview.md for the full architecture guide.

Agent Skill

This repo's conventions are available as portable agent skills in skills/.

License

Apache-2.0

Directories

Path Synopsis
cmd
dispatch command
Command dispatch is the control plane binary.
Command dispatch is the control plane binary.
examples
basic command
Basic example: compose a control plane from the orthogonal pieces — a local workspace, a sandboxed tool, an in-process node factory, and an in-memory metrics recorder — then deploy a service, scale it out, submit tasks, and print the resulting metrics.
Basic example: compose a control plane from the orthogonal pieces — a local workspace, a sandboxed tool, an in-process node factory, and an in-memory metrics recorder — then deploy a service, scale it out, submit tasks, and print the resulting metrics.
ngac command
NGAC example: define access as a policy graph instead of flat per-tool policies.
NGAC example: define access as a policy graph instead of flat per-tool policies.
internal
cli
Package cli wires the dispatch command tree: serve, version, update.
Package cli wires the dispatch command tree: serve, version, update.
server
Package server exposes a ControlPlane over HTTP.
Package server exposes a ControlPlane over HTTP.
updater
Package updater replaces the running binary with the latest GitHub release, implementing the portfolio-standard `update` subcommand.
Package updater replaces the running binary with the latest GitHub release, implementing the portfolio-standard `update` subcommand.
pkg
controlplane
Package controlplane defines the deployment surface of dispatch: deploy a single service, scale its agent execution nodes, produce tasks for them, and observe the result.
Package controlplane defines the deployment surface of dispatch: deploy a single service, scale its agent execution nodes, produce tasks for them, and observe the result.
metrics
Package metrics defines the recording interface every dispatch component emits through.
Package metrics defines the recording interface every dispatch component emits through.
ngac
Package ngac implements a Next Generation Access Control (NGAC) policy machine in the style of NIST SP 800-178: a directed acyclic graph of users, user attributes, objects, object attributes, and policy classes, connected by assignments and granted capabilities through associations, with prohibitions as overriding denials.
Package ngac implements a Next Generation Access Control (NGAC) policy machine in the style of NIST SP 800-178: a directed acyclic graph of users, user attributes, objects, object attributes, and policy classes, connected by assignments and granted capabilities through associations, with prohibitions as overriding denials.
node
Package node defines the agent execution node: the unit that consumes tasks and runs tools.
Package node defines the agent execution node: the unit that consumes tasks and runs tools.
node/inproc
Package inproc provides an in-process node.Factory: each node executes tools on the calling goroutine, resolving them from a shared registry and confining each call through the deployment's policy decision point.
Package inproc provides an in-process node.Factory: each node executes tools on the calling goroutine, resolving them from a shared registry and confining each call through the deployment's policy decision point.
queue
Package queue is the producer/consumer seam of dispatch.
Package queue is the producer/consumer seam of dispatch.
queue/httpqueue
Package httpqueue implements queue.Queue and queue.Results over the dispatch control plane's HTTP API.
Package httpqueue implements queue.Queue and queue.Results over the dispatch control plane's HTTP API.
sandbox
Package sandbox confines what agents can touch.
Package sandbox confines what agents can touch.
task
Package task defines the unit of work that flows through dispatch: produced by API clients or by agents spawning sub-tasks, carried by a queue, and consumed by agent execution nodes.
Package task defines the unit of work that flows through dispatch: produced by API clients or by agents spawning sub-tasks, carried by a queue, and consumed by agent execution nodes.
tool
Package tool defines the unit of capability an agent execution node can invoke.
Package tool defines the unit of capability an agent execution node can invoke.
worker
Package worker runs the consumer side of dispatch: a loop that leases tasks from a queue, executes them on a node, and reports results.
Package worker runs the consumer side of dispatch: a loop that leases tasks from a queue, executes them on a node, and reports results.
workspace
Package workspace defines the shared storage backend that every agent execution node mounts.
Package workspace defines the shared storage backend that every agent execution node mounts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL