The CRD is the contract. The saga is the engine. The backend is a choice.
plnt is nine pieces: a CRD, an operator, a Temporal workflow, a workflow-spec pull path, a Helm chart template, a backend-registration resource, a router, a smoke harness, and a rollback path. Each piece is small enough to explain on one screen.
Four layers. plnt is the third. Everything above it consumes; everything below it is Kubernetes.
google-business (or any consumer). A SaaS surface that needs narrow, reliable AI features. Calls the workflow endpoint plnt exposes — same shape for every workflow.
microagents. S3-backed store of workflow specs (steps, tool bindings, GPU requirements). Versioned, hash-verifiable, pullable. Publishing is a git push + a sync job.
plnt. Watches a WorkflowRun CRD → runs a Temporal saga → Helm-installs a runner pod on the chosen backend → canary → promote or rollback.
Any Kubernetes + GPU node pool. plnt speaks to the K8s API; backends are declared once in a PlntBackend resource and referenced by name from every WorkflowRun.
One K8s cluster. One operator. One workflow engine. N workflows.
plnt CLI kubectl google-business
│ │ │
└──────────────┬───────────┘ │
▼ │
┌─────────────────────────────┐ │
│ WorkflowRun (K8s CRD) │ │
└──────────────┬──────────────┘ │
│ watch │
▼ │
┌─────────────────────────────┐ │
│ plnt operator (kopf) │ │
└──────────────┬──────────────┘ │
│ start_workflow(spec) │
▼ │
┌──────────────────────────────────────────┐ │
│ Temporal · OrchestrateWorkflow │ │
│ pull → resolve → helm → smoke → promote │ │
│ └──────────────┴──────────▶ rollback │
└──────────────────────────────────────────┘ │
│ helm install │
▼ │
┌──────────────────────────────────────────┐ │
│ workflow runner pod │ │
│ ─ pulls spec from microagents (S3) │ │
│ ─ mounts tools declared in spec │ │
│ ─ exposes /invoke on OpenAPI shape │ │
└──────────────────────────────────────────┘ │
│ │
▼ │
┌──────────────┐ │
│ envoy router │ (VirtualService weights) │
└──────┬───────┘ │
▼ │
/invoke ◀───────────────────────────────── consume
The WorkflowRun resource is the entire deploy contract. Everything the operator, the saga, and the Helm chart need is on the spec.
apiVersion: plnt.work/v1
kind: WorkflowRun
metadata:
name: review-responder
spec:
workflow:
ref: review-responder@1.2.0
registry: s3://microagents # or oci://ghcr.io/...
integrityHash: sha256:9a1b... # optional pin
backend:
cluster: gpu-cluster-01 # named plnt backend
gpuClass: nvidia.com/h100
gpuCount: 2
nodeSelector:
pool: agent-workflows
replicas:
min: 1
max: 4
autoscaling:
targetInvocationsPerSecond: 25
canary:
trafficPercent: 5
smokeTest:
invocations: 10
p95BudgetMs: 2500
errorBudgetPercent: 1 The thing plnt pulls from the registry. A workflow is a directed graph of steps + tool bindings + resource requirements.
# microagents/review-responder/workflow.yaml
apiVersion: microagents.dev/v1
kind: Workflow
metadata:
name: review-responder
version: 1.2.0
spec:
description: Draft an on-brand reply to a Google Business review.
runtime:
image: ghcr.io/microagents/runner:0.4.0
entrypoint: python -m review_responder
steps:
- id: classify_intent # sentiment + topic
tool: llm.classify
- id: retrieve_brand_voice # RAG from tenant KB
tool: rag.query
deps: [classify_intent]
- id: draft_reply
tool: llm.generate
deps: [retrieve_brand_voice]
- id: safety_check
tool: policy.moderate
deps: [draft_reply]
requirements:
gpuClass: nvidia.com/h100
gpuCount: 2
memoryGiB: 40 A Python kopf controller watches the CRD. Create / update / delete map directly to Temporal workflow starts, updates, and cancellations.
# plnt/operators/workflowrun_controller.py
import kopf
from temporalio.client import Client
from plnt.workflows.orchestrate import OrchestrateWorkflow
@kopf.on.create('plnt.work', 'v1', 'workflowruns')
async def on_create(spec, name, namespace, **_):
client = await Client.connect(TEMPORAL_ADDR)
await client.start_workflow(
OrchestrateWorkflow.run,
args=[spec],
id=f'orchestrate-{namespace}-{name}',
task_queue='plnt-orchestrate',
)
@kopf.on.update('plnt.work', 'v1', 'workflowruns')
async def on_update(spec, name, namespace, **_):
# Any spec change triggers a fresh canary.
...
@kopf.on.delete('plnt.work', 'v1', 'workflowruns')
async def on_delete(name, namespace, **_):
# helm uninstall + cancel any in-flight orchestration.
... The orchestration saga is a Temporal workflow. Compensation on failure via helm rollback. Retries per activity, non-retryable error types short-circuit obvious dead-ends.
# plnt/workflows/orchestrate.py
from datetime import timedelta
from temporalio import workflow
from temporalio.common import RetryPolicy
@workflow.defn
class OrchestrateWorkflow:
@workflow.run
async def run(self, spec: dict) -> dict:
retry = RetryPolicy(
initial_interval=timedelta(seconds=2),
maximum_attempts=3,
backoff_coefficient=2.0,
non_retryable_error_types=['SpecInvalid', 'BackendUnavailable'],
)
try:
await workflow.execute_activity(
pull_workflow_spec, spec, start_to_close_timeout=timedelta(minutes=5), retry_policy=retry)
await workflow.execute_activity(
resolve_backend, spec, start_to_close_timeout=timedelta(seconds=30), retry_policy=retry)
release = await workflow.execute_activity(
helm_install_canary, spec, start_to_close_timeout=timedelta(minutes=10), retry_policy=retry)
smoke = await workflow.execute_activity(
run_smoke_test, release, start_to_close_timeout=timedelta(minutes=5), retry_policy=retry)
if not smoke['passed']:
await workflow.execute_activity(helm_rollback, release)
return {'status': 'rolled_back', 'reason': smoke['reason']}
await workflow.execute_activity(
promote_to_stable, release, start_to_close_timeout=timedelta(minutes=5))
return {'status': 'ready', 'endpoint': release['endpoint']}
except Exception:
await workflow.execute_activity(helm_rollback, spec) # compensation
raise One orchestration. Captured from the Temporal event history for orchestrate-default-review-responder.
The numbers that prove the runtime works: p50/p95/p99 per-invocation latency, error rate, GPU utilization, queue depth. Scraped from each workflow's /metrics endpoint into Prometheus.
latency p50 = 1.10 s p95 = 1.82 s p99 = 2.41 s error rate = 0.00 % throughput = 9.7 invocations/s gpu utilization = 68 % step-cache hit rate = 34 %
Where the current build is honest about what it isn't. Named upfront, not hidden.
microagents ships a pull path; the push path is a manual S3 sync. A proper microagents publish CLI + signature verification is planned Q1 2026.
Single-cluster demo today. Multi-cluster is a design I understand (fan-out activities keyed by cluster context; per-cluster canary) but not yet code I've run at scale.
plnt respects nvidia.com/gpu limits and node selectors; it does not yet do capacity-aware placement across pools. The scheduler-plugin work is Phase 5.
Temporal history + Kubernetes events cover the deploy lane. Per-invocation tracing (OpenTelemetry span per workflow step) is stubbed but not wired to a collector yet.