Status: v0.3.0 — routing, registry client, and full package attestation implemented. Spec: WCP_SPEC.md Production implementation: pip install pyhall-wcp
This is the Go implementation of WCP — Worker Class Protocol, an open standard for governing worker dispatch in AI agent systems.
The Python reference implementation (pyhall) is the production-ready version. This Go package mirrors its type system and routing interfaces so Go services can participate in a WCP-governed worker fleet.
If you need production routing or package attestation today: use PyHall.
pip install pyhall-wcp==0.3.0
pyhall route --capability cap.doc.summarize --env dev --data-label INTERNALThis Go package is for teams that need to write WCP workers or consume WCP routing decisions from a Go service.
github.com/pyhall/pyhall-go
Go 1.22+. Zero external runtime dependencies — stdlib only.
wcp/
models.go — RouteInput, RouteDecision, supporting types
router.go — MakeDecision() — the primary routing entrypoint (stub)
registry.go — Registry — in-memory worker enrollment store
registry_client.go — RegistryClient — HTTP client for api.pyhall.dev
policy_gate.go — PolicyGate interface + DefaultPolicyGate stub
common.go — NowUTC(), SHA256Hex(), OK/Err helpers
workers/examples/hello_worker/
worker.go — minimal canonical worker implementation
registry_record.json — enrollment record for the hello worker
import (
"fmt"
"github.com/pyhall/pyhall-go/wcp"
)
func main() {
registry := wcp.NewRegistry()
// Enroll a worker
err := registry.Enroll(wcp.WorkerRegistryRecord{
WorkerID: "org.example.my-summarizer",
WorkerSpeciesID: "wrk.doc.summarizer",
Capabilities: []string{"cap.doc.summarize"},
RiskTier: "low",
})
if err != nil {
panic(err)
}
// Route a capability request
input := wcp.RouteInput{
CapabilityID: "cap.doc.summarize",
Env: wcp.EnvDev,
DataLabel: wcp.DataLabelInternal,
TenantRisk: wcp.TenantRiskLow,
QoSClass: wcp.QoSP2,
TenantID: "tenant-001",
CorrelationID: "550e8400-e29b-41d4-a716-446655440000",
Request: map[string]any{"text": "Summarize this document..."},
}
decision := wcp.MakeDecision(input, registry, wcp.RouterOptions{})
if decision.Denied {
fmt.Println("Denied:", decision.DenyReasonIfDenied)
} else {
fmt.Println("Route to:", *decision.SelectedWorkerSpeciesID)
}
}Go has parity with Python and TypeScript for the api.pyhall.dev HTTP API.
import "github.com/pyhall/pyhall-go/wcp"
client := wcp.NewRegistryClient(wcp.RegistryClientOptions{
// BaseURL defaults to "https://api.pyhall.dev"
// SessionToken: "your-session-jwt",
// Timeout: 10 * time.Second,
// CacheTTL: 60 * time.Second,
})
// Verify a worker's attestation status
resp, err := client.Verify("org.example.my-worker")
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Status) // "active" | "revoked" | "banned" | "unknown"
fmt.Println(resp.AIGenerated) // bool — was this package AI-assisted?
// Check the ban-list
banned, err := client.IsHashBanned(someHash)
// Fetch all confirmed ban-list entries
entries, err := client.GetBanList(500)
// Registry health check
h, err := client.Health()
// Pre-populate cache before routing
err = client.Prefetch([]string{"org.example.worker-a", "org.example.worker-b"})
// Synchronous hash lookup (uses cache populated by Prefetch)
hash, ok := client.GetWorkerHash("org.example.worker-a")VerifyResponse fields: WorkerID, Status, CurrentHash, Banned,
BanReason, AttestedAt, AIGenerated, AIService, AIModel,
AISessionFingerprint.
Override the registry URL via RegistryClientOptions.BaseURL or set the
PYHALL_REGISTRY_URL environment variable.
Full-package attestation is fully implemented in v0.3.0:
import "github.com/pyhall/pyhall-go/wcp"
// Build + sign a manifest at CI/deploy time
manifest, err := wcp.BuildManifest(wcp.BuildManifestOptions{
PackageRoot: "/opt/workers/my-worker",
WorkerID: "org.example.my-worker.i-1",
WorkerSpeciesID: "wrk.example.my-worker",
WorkerVersion: "1.0.0",
SigningSecret: os.Getenv("WCP_ATTEST_HMAC_KEY"),
})
wcp.WriteManifest(manifest, "/opt/workers/my-worker/manifest.json")
// Verify at runtime (fail-closed)
v := &wcp.PackageAttestationVerifier{
PackageRoot: "/opt/workers/my-worker",
ManifestPath: "/opt/workers/my-worker/manifest.json",
WorkerID: "org.example.my-worker.i-1",
WorkerSpeciesID: "wrk.example.my-worker",
}
result := v.Verify()
if !result.OK {
log.Fatalf("Attestation denied: %s", result.DenyCode)
}| Requirement | Status |
|---|---|
| Capability routing | Stub (workers enrolled via Registry) |
| Fail-closed (unknown capability = deny) | Done |
| Deterministic routing | Done |
| Controls enforcement | TODO |
| Mandatory telemetry | Done (three events emitted) |
| Dry-run support | Done |
| Blast radius scoring | TODO |
| Policy gate | Stub (DefaultPolicyGate passes through) |
| Evidence receipts | Done (in hello_worker example) |
| Discovery API | TODO |
| Registry client (api.pyhall.dev) | Done |
| Package attestation | Not yet ported |
Full WCP-Standard and WCP-Full compliance requires completing the TODOs in
router.go and policy_gate.go.
WCP (Worker Class Protocol) defines the governance layer between a capability request and its execution. It answers: should this worker be trusted with this job, under these conditions, with this data?
Every protocol in the agent ecosystem — MCP, A2A, ACP — defines how agents communicate. None define whether a worker should be trusted to execute. WCP fills that gap.
Agent reasoning
|
WCP Hall (capability request → governed routing → dispatch)
|
Transport (MCP, HTTP, A2A, subprocess)
|
Worker execution
Read the full spec: WCP_SPEC.md
Apache 2.0. See LICENSE.