Skip to content

Quick Start

1. Install

Terminal window
pip install pyhall-wcp

Requires Python 3.10+. No mandatory external dependencies beyond Pydantic v2.

2. Build a Worker Registry Record

The pyhall build command launches an interactive wizard that generates a registry record — the enrollment document a worker submits to the Hall. It declares capabilities, risk tier, controls, and blast radius.

Terminal window
pyhall build

The wizard prompts for worker ID, capabilities, risk tier, controls, and privilege envelope, then writes the file. A generated registry_record.json will look like this:

{
"worker_id": "org.acme.summarizer",
"worker_species_id": "wrk.doc.summarizer",
"capabilities": ["cap.doc.summarize"],
"risk_tier": "low",
"idempotency": "full",
"determinism": "captured",
"required_controls": ["ctrl.obs.audit-log-append-only"],
"currently_implements": ["ctrl.obs.audit-log-append-only"],
"allowed_environments": ["dev", "stage", "prod"],
"privilege_envelope": {
"secrets_access": [],
"network_egress": "none",
"filesystem_writes": ["/tmp/summaries/"],
"tools": []
},
"blast_radius": {
"data": 1,
"network": 0,
"financial": 0,
"time": 1,
"reversibility": "reversible"
},
"owner": "org.acme",
"contact": "you@acme.com",
"artifact_hash": "sha256:...",
"catalog_version_min": "1.0.0"
}

3. Start the Hall API

Terminal window
python -m hall_api.server

The Hall API starts on http://localhost:8765 by default. It loads routing rules from rules.json and enrolled workers from the enrolled/ directory in the current working directory.

Check it is running:

Terminal window
curl http://localhost:8765/health

4. Enroll the Worker

Terminal window
curl -X POST http://localhost:8765/enroll \
-H "Content-Type: application/json" \
-d @my_summarizer/registry_record.json

The Hall verifies the artifact_hash on receipt. A mismatch means the registry record was modified after it was generated — enrollment is rejected.

Successful enrollment response:

{
"enrolled": true,
"enrollment_id": "enr_7a3f9c2b",
"worker_id": "org.acme.summarizer",
"artifact_hash_verified": true,
"enrolled_at": "2026-02-25T00:00:00Z"
}

5. Make a Routing Decision

Use make_decision() directly in Python or the pyhall route CLI. The Hall API server does not expose a /route HTTP endpoint — routing is done in-process via the SDK.

import uuid
from pyhall import make_decision, RouteInput, Registry, load_rules
# Load routing rules and enrolled workers
rules = load_rules("rules.json")
registry = Registry(registry_dir="enrolled/")
# Build a capability request
inp = RouteInput(
capability_id="cap.doc.summarize",
env="dev",
data_label="INTERNAL",
tenant_risk="low",
qos_class="P2",
tenant_id="org.acme",
correlation_id=str(uuid.uuid4()),
)
# Ask the Hall
decision = make_decision(
inp=inp,
rules=rules,
registry_controls_present=registry.controls_present(),
registry_worker_available=registry.worker_available,
)
if decision.denied:
print(f"Denied: {decision.deny_reason_if_denied}")
else:
print(f"Dispatch: {decision.selected_worker_species_id}")
# -> wrk.doc.summarizer

6. What You Get Back

Every routing decision — allowed or denied — returns a complete RouteDecision:

{
"decision_id": "550e8400-e29b-41d4-a716-446655440001",
"timestamp": "2026-02-25T12:00:00Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "org.acme",
"capability_id": "cap.doc.summarize",
"matched_rule_id": "rr_doc_summarize_dev",
"selected_worker_species_id": "wrk.doc.summarizer",
"env": "dev",
"data_label": "INTERNAL",
"tenant_risk": "low",
"qos_class": "P2",
"denied": false,
"deny_reason_if_denied": null,
"required_controls_effective": ["ctrl.obs.audit-log-append-only"],
"escalation_effective": {
"policy_gate": true,
"human_required_default": false
},
"artifact_hash": "sha256:7b3f9c2a...",
"worker_attestation_checked": false,
"dry_run": false,
"telemetry_envelopes": [
{"event_id": "evt.os.task.routed", "timestamp": "2026-02-25T12:00:00Z", "correlation_id": "550e8400..."},
{"event_id": "evt.os.worker.selected","timestamp": "2026-02-25T12:00:00Z", "correlation_id": "550e8400..."},
{"event_id": "evt.os.policy.gated", "timestamp": "2026-02-25T12:00:00Z", "correlation_id": "550e8400..."}
]
}

The artifact_hash proves exactly what was routed. The telemetry_envelopes carry the three mandatory WCP events. The correlation_id propagates through all downstream worker calls.

Next Steps