Summary
Define and implement the AgentCapability Custom Resource Definition (CRD) - a Kubernetes-native way to represent services that can be registered on-chain via ERC-8004.
Background
The orchestrator needs a Kubernetes-native mechanism to discover and track services deployed in the stack. Following established patterns (ServiceMonitor for Prometheus, Certificate for cert-manager), we'll use a CRD that:
- Networks emit when deployed (e.g., ethereum creates an RPC capability)
- The orchestrator controller watches and reconciles
- Drives ERC-8004 registration and HTTPRoute generation
See Orchestrator PRD for full context.
Requirements
Must Have
Should Have
Nice to Have
CRD Specification
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: agentcapabilities.obol.network
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
spec:
group: obol.network
names:
plural: agentcapabilities
singular: agentcapability
kind: AgentCapability
shortNames:
- acap
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
subresources:
status: {}
additionalPrinterColumns:
- name: Type
type: string
jsonPath: .spec.type
- name: Published
type: boolean
jsonPath: .spec.publish
- name: Registered
type: boolean
jsonPath: .status.registered
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
schema:
openAPIV3Schema:
type: object
required:
- spec
properties:
spec:
type: object
required:
- type
- endpoint
properties:
type:
type: string
description: "Type of capability being offered"
enum:
- rpc
- inference
- fine-tune
- validator
protocol:
type: string
description: "Protocol identifier (e.g., ethereum-json-rpc, openai-chat)"
chain:
type: object
description: "Blockchain network details (for rpc type)"
properties:
id:
type: integer
description: "Chain ID (e.g., 1 for mainnet)"
name:
type: string
description: "Human-readable network name"
pricing:
type: object
description: "Payment requirements for this capability"
properties:
model:
type: string
description: "Pricing model"
enum:
- per-request
- per-token
- per-epoch
- per-hour
- free
default: per-request
amount:
type: string
description: "Price amount in asset units (e.g., '0.0001')"
default: "0"
asset:
type: string
description: "Payment asset symbol"
default: "USDC"
network:
type: string
description: "Payment network (e.g., base, base-sepolia)"
default: "base-sepolia"
endpoint:
type: object
required:
- service
- port
description: "Kubernetes service endpoint"
properties:
service:
type: string
description: "Kubernetes service name"
port:
type: integer
description: "Service port number"
path:
type: string
description: "URL path prefix"
default: "/"
publish:
type: boolean
description: "Whether to publish this capability to ERC-8004"
default: true
status:
type: object
properties:
registered:
type: boolean
description: "Whether capability is registered on-chain"
agentId:
type: integer
description: "ERC-8004 agent NFT ID"
registryTxHash:
type: string
description: "Transaction hash of registration"
tunnelPath:
type: string
description: "Public URL path via cloudflared"
httpRouteName:
type: string
description: "Generated HTTPRoute resource name"
lastSync:
type: string
format: date-time
description: "Last successful reconciliation"
conditions:
type: array
items:
type: object
properties:
type:
type: string
status:
type: string
lastTransitionTime:
type: string
format: date-time
reason:
type: string
message:
type: string
Example Resources
Ethereum RPC Capability
apiVersion: obol.network/v1alpha1
kind: AgentCapability
metadata:
name: execution-rpc
namespace: ethereum-knowing-wahoo
spec:
type: rpc
protocol: ethereum-json-rpc
chain:
id: 1
name: mainnet
pricing:
model: per-request
amount: "0.0001"
asset: USDC
network: base-sepolia
endpoint:
service: ethereum-execution-reth-mainnet
port: 8545
path: /
publish: true
Inference Capability
apiVersion: obol.network/v1alpha1
kind: AgentCapability
metadata:
name: llama-inference
namespace: unsloth
spec:
type: inference
protocol: openai-chat
pricing:
model: per-token
amount: "0.00001"
asset: USDC
network: base-sepolia
endpoint:
service: unsloth-api
port: 8000
path: /v1/chat/completions
publish: true
Fine-tuning Capability
apiVersion: obol.network/v1alpha1
kind: AgentCapability
metadata:
name: unsloth-finetune
namespace: unsloth
spec:
type: fine-tune
protocol: unsloth-v1
pricing:
model: per-epoch
amount: "1.00"
asset: USDC
network: base-sepolia
endpoint:
service: unsloth-api
port: 8000
path: /v1/fine-tune
publish: true
Implementation
Option A: Static YAML (MVP)
Add CRD manifest to internal/embed/infrastructure/:
internal/embed/infrastructure/
├── helmfile.yaml
├── crds/
│ └── agentcapability-crd.yaml # NEW
└── ...
Deploy via raw chart in helmfile:
- name: obol-crds
namespace: kube-system
chart: bedag/raw
values:
- resources:
- {{ readFile "crds/agentcapability-crd.yaml" | nindent 10 }}
Option B: Controller-gen (Production)
Use kubebuilder/controller-gen for type-safe Go types:
// internal/api/v1alpha1/agentcapability_types.go
package v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.spec.type`
// +kubebuilder:printcolumn:name="Published",type=boolean,JSONPath=`.spec.publish`
// +kubebuilder:printcolumn:name="Registered",type=boolean,JSONPath=`.status.registered`
type AgentCapability struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AgentCapabilitySpec `json:"spec,omitempty"`
Status AgentCapabilityStatus `json:"status,omitempty"`
}
type AgentCapabilitySpec struct {
Type CapabilityType `json:"type"`
Protocol string `json:"protocol,omitempty"`
Chain *ChainSpec `json:"chain,omitempty"`
Pricing *PricingSpec `json:"pricing,omitempty"`
Endpoint EndpointSpec `json:"endpoint"`
Publish bool `json:"publish,omitempty"`
}
// +kubebuilder:validation:Enum=rpc;inference;fine-tune;validator
type CapabilityType string
// ... rest of types
Recommendation: Start with Option A for MVP, migrate to Option B when building the controller.
Files to Create/Modify
internal/embed/infrastructure/crds/agentcapability-crd.yaml - CRD manifest
internal/embed/infrastructure/helmfile.yaml - Add CRD deployment
internal/embed/networks/ethereum/helmfile.yaml.gotmpl - Emit AgentCapability on install
internal/embed/networks/helios/helmfile.yaml.gotmpl - Emit AgentCapability on install
internal/embed/networks/aztec/helmfile.yaml.gotmpl - Emit AgentCapability on install
Testing
# Deploy stack with CRD
obol stack up
# Verify CRD registered
obol kubectl get crd agentcapabilities.obol.network
# Install network (should create AgentCapability)
obol network install ethereum --network=mainnet
# List capabilities
obol kubectl get agentcapabilities -A
# or
obol kubectl get acap -A
# Describe capability
obol kubectl describe acap execution-rpc -n ethereum-<id>
Dependencies
- Depends on: None (can be done in parallel with Traefik migration)
- Blocks: Orchestrator controller implementation
Related
Summary
Define and implement the
AgentCapabilityCustom Resource Definition (CRD) - a Kubernetes-native way to represent services that can be registered on-chain via ERC-8004.Background
The orchestrator needs a Kubernetes-native mechanism to discover and track services deployed in the stack. Following established patterns (ServiceMonitor for Prometheus, Certificate for cert-manager), we'll use a CRD that:
See Orchestrator PRD for full context.
Requirements
Must Have
AgentCapabilityCRD schema (v1alpha1)obol stack uprpc,inference,fine-tune,validatorpublishflag to control visibilityShould Have
acap) for kubectlNice to Have
kubectl get agentcapabilitiesCRD Specification
Example Resources
Ethereum RPC Capability
Inference Capability
Fine-tuning Capability
Implementation
Option A: Static YAML (MVP)
Add CRD manifest to
internal/embed/infrastructure/:Deploy via raw chart in helmfile:
Option B: Controller-gen (Production)
Use kubebuilder/controller-gen for type-safe Go types:
Recommendation: Start with Option A for MVP, migrate to Option B when building the controller.
Files to Create/Modify
internal/embed/infrastructure/crds/agentcapability-crd.yaml- CRD manifestinternal/embed/infrastructure/helmfile.yaml- Add CRD deploymentinternal/embed/networks/ethereum/helmfile.yaml.gotmpl- Emit AgentCapability on installinternal/embed/networks/helios/helmfile.yaml.gotmpl- Emit AgentCapability on installinternal/embed/networks/aztec/helmfile.yaml.gotmpl- Emit AgentCapability on installTesting
Dependencies
Related