Go SDK
pyhall-go mirrors the WCP type system and routing interfaces so Go services can participate in a WCP-governed worker fleet. It is for teams that need to write WCP workers or consume WCP routing decisions from a Go service.
Module: github.com/pyhall/pyhall-go
Go: 1.22+. Zero external runtime dependencies — stdlib only.
WCP compliance: WCP-Basic (partial). See the compliance status table below.
Install
go get github.com/pyhall/pyhall-go@latestQuick Start
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) }}Package Layout
wcp/ models.go — RouteInput, RouteDecision, supporting types router.go — MakeDecision() — primary routing entrypoint (stub) registry.go — Registry — in-memory worker enrollment store 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 workerTypes
Enum Constants
type Env stringconst ( EnvDev Env = "dev" EnvStage Env = "stage" EnvProd Env = "prod" EnvEdge Env = "edge")
type DataLabel stringconst ( DataLabelPublic DataLabel = "PUBLIC" DataLabelInternal DataLabel = "INTERNAL" DataLabelRestricted DataLabel = "RESTRICTED")
type QoSClass stringconst ( QoSP0 QoSClass = "P0" QoSP1 QoSClass = "P1" QoSP2 QoSClass = "P2" QoSP3 QoSClass = "P3")
type TenantRisk stringconst ( TenantRiskLow TenantRisk = "low" TenantRiskMedium TenantRisk = "medium" TenantRiskHigh TenantRisk = "high")RouteInput
type RouteInput struct { CapabilityID string `json:"capability_id"` Env Env `json:"env"` DataLabel DataLabel `json:"data_label"` TenantRisk TenantRisk `json:"tenant_risk"` QoSClass QoSClass `json:"qos_class"` TenantID string `json:"tenant_id"` CorrelationID string `json:"correlation_id"` Request map[string]any `json:"request,omitempty"` BlastRadius map[string]any `json:"blast_radius,omitempty"` BlastScore *int `json:"blast_score,omitempty"` PrivilegeContext map[string]any `json:"privilege_context,omitempty"` DryRun bool `json:"dry_run"`}RouteDecision
type RouteDecision struct { DecisionID string `json:"decision_id"` Timestamp string `json:"timestamp"` CorrelationID string `json:"correlation_id"` TenantID string `json:"tenant_id"` CapabilityID string `json:"capability_id"` MatchedRuleID string `json:"matched_rule_id"` Env Env `json:"env"` DataLabel DataLabel `json:"data_label"` TenantRisk TenantRisk `json:"tenant_risk"` QoSClass QoSClass `json:"qos_class"` Denied bool `json:"denied"` DenyReasonIfDenied map[string]any `json:"deny_reason_if_denied,omitempty"` SelectedWorkerSpeciesID *string `json:"selected_worker_species_id,omitempty"` CandidateWorkersRanked []CandidateWorker `json:"candidate_workers_ranked"` RequiredControlsEffective []string `json:"required_controls_effective"` RecommendedProfilesEffective []map[string]any `json:"recommended_profiles_effective"` EscalationEffective Escalation `json:"escalation_effective"` // ... additional governance fields TelemetryEnvelopes []map[string]any `json:"telemetry_envelopes"`}CandidateWorker
type CandidateWorker struct { WorkerSpeciesID string `json:"worker_species_id"` ScoreHint *float64 `json:"score_hint,omitempty"` RequiresControlsMinimum []string `json:"requires_controls_minimum,omitempty"` SkipReason *string `json:"skip_reason,omitempty"`}Escalation
type Escalation struct { PolicyGate bool `json:"policy_gate"` MSAVXStepUp bool `json:"msavx_step_up"` HumanRequiredDefault bool `json:"human_required_default"` HumanRequiredIf []map[string]any `json:"human_required_if,omitempty"` Rationale *string `json:"rationale,omitempty"`}MakeDecision()
type RouterOptions struct { // Options for future extension (controls enforcement, blast radius, etc.)}
func MakeDecision(inp RouteInput, registry *Registry, opts RouterOptions) RouteDecisionThe current stub routes to the first enrolled worker that handles the requested capability. Returns a denied decision if no worker is available. Always emits three mandatory telemetry events.
Registry
func NewRegistry() *Registry
func (r *Registry) Enroll(record WorkerRegistryRecord) errorfunc (r *Registry) WorkersForCapability(capabilityID string) []WorkerRegistryRecordfunc (r *Registry) Get(workerID string) (WorkerRegistryRecord, bool)func (r *Registry) AllWorkers() []WorkerRegistryRecordfunc (r *Registry) AllCapabilities() []stringfunc (r *Registry) ControlsPresent(controlIDs []string) (bool, string)// ControlsPresent checks whether all given control IDs are present.// Returns (true, "") when all are present; (false, missingControlID) on first miss.
// To check if a species is available for dispatch, use WorkersForCapability() and// check whether the returned slice is non-empty.// To get the enrolled worker count: len(registry.AllWorkers())WorkerRegistryRecord
type WorkerRegistryRecord struct { WorkerID string `json:"worker_id"` WorkerSpeciesID string `json:"worker_species_id"` Capabilities []string `json:"capabilities"` RiskTier string `json:"risk_tier,omitempty"` RequiredControls []string `json:"required_controls,omitempty"` CurrentlyImplements []string `json:"currently_implements,omitempty"` AllowedEnvironments []string `json:"allowed_environments,omitempty"` BlastRadius map[string]any `json:"blast_radius,omitempty"` PrivilegeEnvelope map[string]any `json:"privilege_envelope,omitempty"` Owner string `json:"owner,omitempty"` Contact string `json:"contact,omitempty"`}WCP Compliance Status
| 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 |
Full WCP-Standard and WCP-Full compliance requires completing the TODOs in router.go and policy_gate.go.
CLI
The Go CLI (pyhall) provides catalog search and worker scaffolding.
go install github.com/pyhall/pyhall-go/cmd/pyhall@latestpyhall search "document summarization"pyhall explain cap.doc.summarizepyhall browsepyhall buildpyhall version