Package v1alpha1 contains API Schema definitions for the agents v1alpha1 API group.
AgentFleet is a Platform-scoped composition of one or more agents on top
of upstream kagent CRs. The scale subresource is deliberately omitted:
kubectl scale would be ambiguous (min? max? per-agent?) for a fleet,
so per-agent replica overrides live on AgentSpec.Replicas and fleet-wide
behavior is driven by .spec.scaling (KEDA) instead.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
agents.nanohype.dev/v1alpha1 |
||
kind string |
AgentFleet |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec AgentFleetSpec |
|||
status AgentFleetStatus |
AgentFleetSpec composes kagent Agent / ModelConfig / ToolServer CRs plus platform-specific scaffolding (KEDA, NetworkPolicy, IRSA binding).
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
|||
agents AgentSpec array |
Agents is the list of agents to provision in this fleet. | MinItems: 1 |
|
scaling ScalingSpec |
Scaling controls KEDA's ScaledObject for the runtime Deployments. | Optional: {} |
AgentFleetStatus reports rollout state.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Provisioning, Ready, ScaledToZero, Failed. | Optional: {} |
|
readyAgents integer |
ReadyAgents counts agents whose downstream Deployment is ready. | Optional: {} |
|
observedGeneration integer |
ObservedGeneration is the last spec.generation reconciled. | Optional: {} |
|
conditions Condition array |
Optional: {} |
AgentSandbox is a Platform-scoped, single-use isolated pod for one agent role-session. It shares SandboxPool's hardening — Pod Security "restricted", default-deny networked, on the dedicated tainted node pool — but is push-dispatched (one session, run-once) rather than a pull-based pool of always-on workers.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
agents.nanohype.dev/v1alpha1 |
||
kind string |
AgentSandbox |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec AgentSandboxSpec |
|||
status AgentSandboxStatus |
AgentSandboxSpec declares one ephemeral, hardened pod that runs a single
agent role-session — fab's sdk role-loop dispatched per session. The
reconciler builds the pod on the dedicated, tainted sandbox node pool,
locked down by a default-deny NetworkPolicy, under the Platform's tenant
IRSA ServiceAccount.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
PlatformRef is the owning Platform. The session pod runs in that Platform's tenant namespace and the sandbox gates on Platform readiness. |
||
image string |
Image is the container image the session pod runs. | ||
command string array |
Command overrides the image entrypoint. | Optional: {} |
|
args string array |
Args are the container arguments. | Optional: {} |
|
env EnvVar array |
Env is the session pod's environment. The dispatcher (fab) passes the role, the role message, and any backend config through here. |
Optional: {} |
|
runtimeClassName string |
RuntimeClassName selects a Kubernetes RuntimeClass for the session pod — "gvisor" or "kata" for kernel-level isolation of the untrusted agent code. The named RuntimeClass must already exist. Empty uses the cluster's default runtime. |
Optional: {} |
|
resources ResourceRequirements |
Resources are the session pod's resource requests and limits. | Optional: {} |
|
ttlSecondsAfterFinished integer |
TTLSecondsAfterFinished is how long the AgentSandbox is kept after its session pod terminates before the operator garbage-collects it. |
3600 | Minimum: 0 Optional: {} |
AgentSandboxStatus reports the sandbox's reconciled state.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Running, Succeeded, Failed, Suspended. | Optional: {} |
|
podName string |
PodName is the session pod's name in the tenant namespace. | Optional: {} |
|
podPhase string |
PodPhase mirrors the session pod's status.phase. | Optional: {} |
|
completedAt Time |
CompletedAt is when the session pod first reached a terminal phase — the start of the TTL countdown. |
Optional: {} |
|
observedGeneration integer |
ObservedGeneration is the last spec.generation reconciled. | Optional: {} |
|
conditions Condition array |
Optional: {} |
AgentSpec is one agent in the fleet.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
|||
systemPrompt string |
SystemPrompt is the agent's instruction text. | ||
modelRoute string |
ModelRoute is the named route on the Platform's ModelGateway. | ||
tools ToolRef array |
Tools is the list of kagent ToolServer references. | Optional: {} |
|
replicas integer |
Replicas overrides the fleet-wide scaling minimum for this agent. | Optional: {} |
BatchJob runs a single Amazon Bedrock batch-inference job for a Platform tenant.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
agents.nanohype.dev/v1alpha1 |
||
kind string |
BatchJob |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec BatchJobSpec |
|||
status BatchJobStatus |
BatchJobSpec submits an Amazon Bedrock batch-inference job (CreateModelInvocationJob): an S3 JSONL of records in, an S3 JSONL of results out. One BatchJob maps to exactly one Bedrock job — there is no schedule; create a new CR for each run (the reconciler is idempotent on the spec, so re-applying the same CR never double-submits).
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
|||
modelId string |
ModelID is the Bedrock model id or inference-profile id the batch job invokes (e.g. "anthropic.claude-3-5-sonnet-20241022-v2:0" or a cross-region "us.anthropic.…" profile). Validated server-side by Bedrock; kept a free string here like Identity.AllowedModels. |
MinLength: 1 |
|
modelInvocationType string |
ModelInvocationType selects the record schema in the input JSONL — raw InvokeModel bodies or Converse turns. |
InvokeModel | Enum: [InvokeModel Converse] |
inputS3Uri string |
InputS3Uri is the s3:// URI of the input JSONL (or its prefix). | Pattern: ^s3://.+ |
|
outputS3Prefix string |
OutputS3Prefix is the s3:// prefix Bedrock writes results under. | Pattern: ^s3://.+ |
|
timeoutHours integer |
TimeoutHours bounds the job's runtime. Bedrock requires 24..168. | 24 | Maximum: 168 Minimum: 24 |
serviceRoleArnOverride string |
ServiceRoleArnOverride replaces the operator-resolved Bedrock batch service role (the role Bedrock assumes to read input / write output). Normally empty — the reconciler injects the SSM-resolved role. |
Optional: {} |
BatchJobStatus tracks the Bedrock job the reconciler submitted and polls.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
jobArn string |
JobArn is the submitted job's ARN. Non-empty is the idempotency guard: once set, the reconciler polls rather than re-submitting. |
Optional: {} |
|
jobName string |
JobName is the deterministic, Bedrock-sanitized job name. | Optional: {} |
|
phase string |
Phase: Pending, Provisioning, Running, Succeeded, Failed, Stopped. | Optional: {} |
|
submittedAt Time |
SubmittedAt / CompletedAt timestamps. | Optional: {} |
|
completedAt Time |
Optional: {} |
||
outputLocation string |
OutputLocation is the s3:// URI Bedrock reports for the results. | Optional: {} |
|
recordCount integer |
RecordCount / SucceededCount / FailedCount mirror Bedrock's ProcessedRecordCount / SuccessRecordCount / ErrorRecordCount once the job is running or terminal. |
Optional: {} |
|
succeededCount integer |
Optional: {} |
||
failedCount integer |
Optional: {} |
||
message string |
Message carries the last Bedrock status / failure reason. | Optional: {} |
|
conditions Condition array |
Optional: {} |
ModelGateway is a per-Platform gateway CR that fronts Bedrock for one or more named routes.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
agents.nanohype.dev/v1alpha1 |
||
kind string |
ModelGateway |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec ModelGatewaySpec |
|||
status ModelGatewayStatus |
ModelGatewaySpec configures a per-Platform gateway: the routes exposed, which Bedrock models back them, and which Guardrail attaches.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
PlatformRef is the owning Platform. | ||
routes ModelRouteSpec array |
Routes is the list of named routes the gateway exposes. | MinItems: 1 |
|
defaultGuardrailRef LocalRef |
DefaultGuardrailRef applies when a Route does not specify its own. | Optional: {} |
ModelGatewayStatus surfaces the agentgateway Route/Listener state.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Provisioning, Ready, Failed. | Optional: {} |
|
endpoint string |
Endpoint is the cluster-internal hostname of the gateway. | Optional: {} |
|
observedGeneration integer |
ObservedGeneration is the last spec.generation reconciled. | Optional: {} |
|
conditions Condition array |
Optional: {} |
ModelRouteSpec is a single named route.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
|||
modelFamily string |
ModelFamily: anthropic | meta | mistral | cohere | amazon-titan | amazon-nova | stability. |
Enum: [anthropic meta mistral cohere amazon-titan amazon-nova stability] |
|
modelId string |
ModelId is the canonical Bedrock model ID or inference profile ID. | ||
crossRegionProfile string |
CrossRegionProfile enables a Bedrock cross-region inference profile. | Optional: {} |
|
rateLimit integer |
RateLimit caps requests per minute (not tokens) on this route. The operator renders it into an agentgateway local rate-limit policy with unit=Minutes; 0 or unset disables rate limiting for the route. |
Optional: {} |
|
guardrailRef LocalRef |
GuardrailRef overrides the gateway's default guardrail. | Optional: {} |
SandboxPool is a Platform-scoped pool of Managed Agents self-hosted sandbox workers. The reconciler runs them as a Deployment on the dedicated, tainted sandbox node pool, locked down by a default-deny NetworkPolicy.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
agents.nanohype.dev/v1alpha1 |
||
kind string |
SandboxPool |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec SandboxPoolSpec |
|||
status SandboxPoolStatus |
SandboxPoolSpec declares a pool of Managed Agents self-hosted sandbox
workers for a self_hosted environment. The workers run Anthropic's
ant beta:worker, claiming sessions from the environment's work queue
and executing agent tool calls inside the cluster.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
PlatformRef is the owning Platform. The pool's workers run in that Platform's tenant namespace and the pool gates on Platform readiness. |
||
environmentId string |
EnvironmentID is the Managed Agents self_hosted environment whose work queue these workers drain (an env_... id). |
||
environmentKeySecret SecretKeySelector |
EnvironmentKeySecret holds ANTHROPIC_ENVIRONMENT_KEY — the worker's auth token, mounted into every worker pod. |
||
apiKeySecret SecretKeySelector |
APIKeySecret holds the organization API key. It is consumed only by the work-queue autoscaler, never mounted into worker pods — Anthropic warns the org key must not be reachable by agent tool calls. |
Optional: {} |
|
image string |
Image overrides the sandbox worker image. Defaults to the platform's published sandbox-worker image when empty. |
Optional: {} |
|
scaling SandboxScalingSpec |
Scaling bounds the worker count. | Optional: {} |
|
resources ResourceRequirements |
Resources are the per-worker-pod resource requests and limits. | Optional: {} |
|
runtimeClassName string |
RuntimeClassName selects a Kubernetes RuntimeClass for the worker pods — typically "gvisor" or "kata" for kernel-level isolation of the untrusted agent tool code. The named RuntimeClass must already exist in the cluster. Empty uses the cluster's default runtime. |
Optional: {} |
SandboxPoolStatus reports the pool's reconciled state.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Ready, Suspended, Failed. | Optional: {} |
|
readyWorkers integer |
ReadyWorkers is the worker Deployment's ready replica count. | Optional: {} |
|
observedGeneration integer |
ObservedGeneration is the last spec.generation reconciled. | Optional: {} |
|
conditions Condition array |
Optional: {} |
SandboxScalingSpec bounds the worker Deployment's replica count.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
minReplicas integer |
MinReplicas is the worker-count floor. A pointer so 0 (scale to zero, for the autoscaled path) is distinguishable from "field absent". |
1 | Minimum: 0 Optional: {} |
maxReplicas integer |
MaxReplicas is the worker-count ceiling for the autoscaler. | 10 | Minimum: 1 Optional: {} |
queueDepthTarget integer |
QueueDepthTarget is the work-queue depth per worker the autoscaler aims for before adding workers. |
5 | Minimum: 1 Optional: {} |
ScalingSpec configures KEDA.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
enabled boolean |
Enabled — when false, the operator scales the Deployment to 0 and removes the ScaledObject. Toggled false by the kill-switch on budget breach. |
true | |
min integer |
Min replicas. Use a pointer so 0 (kill-switch state) is distinguishable from "field absent" — with int32 + omitempty, the zero value gets dropped and re-defaulted, making min=0 unrepresentable. |
1 | Minimum: 0 Optional: {} |
max integer |
Max replicas. | 10 | Minimum: 1 Optional: {} |
queueDepthTrigger integer |
QueueDepthTrigger: scale up when SQS depth exceeds this value. | 10 | Minimum: 1 Optional: {} |
queueUrl string |
QueueUrl is the SQS queue the fleet's work originates from. When set the operator emits a KEDA aws-sqs-queue trigger; otherwise a CPU-utilization placeholder. The tenant IRSA role must have sqs:GetQueueAttributes on this queue (granted via the agent-iam baseline policy + an in-policy resource ARN derived from the URL). |
Pattern: ^https://sqs\.[a-z0-9-]+\.amazonaws\.com/[0-9]\{12\}/[A-Za-z0-9_-]+(\.fifo)?$ Optional: {} |
ToolRef references a kagent ToolServer by name.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
Package v1alpha1 contains API Schema definitions for the governance v1alpha1 API group.
BudgetPolicy caps monthly spend per Platform and triggers the kill-switch at 120% of the threshold.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
governance.nanohype.dev/v1alpha1 |
||
kind string |
BudgetPolicy |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec BudgetPolicySpec |
|||
status BudgetPolicyStatus |
BudgetPolicySpec sets monthly spend caps per Platform.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
|||
monthlyUsd string |
MonthlyUsd is the soft threshold expressed as a decimal-string USD amount (e.g. "2500", "1500.50"). KillSwitch fires at 120% of this. Modeled as string for symmetry with Status.CurrentSpendUsd and so future v1 can support fractional cents without a lossy int32 → string conversion. The pattern enforces non-negative decimal with optional 2-digit fraction. |
MinLength: 1 Pattern: ^[0-9]+(\.[0-9]\{1,2\})?$ |
|
alertThresholdsPercent integer array |
AlertThresholdsPercent — fire WarnEvent at these % of the threshold. | [50 80 100] | Optional: {} |
killSwitchEnabled boolean |
KillSwitchEnabled — when false, breach at 120% is logged but not acted on. Use sparingly; SOC2 platforms must keep this true. |
true |
BudgetPolicyStatus surfaces the latest spend reading. The budget reconciler updates this on every tick (hourly in prod, 5m in dev) with current spend, percent-of-budget, the alert thresholds crossed, and reconcile conditions.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
currentSpendUsd string |
CurrentSpendUsd is the most recent spend snapshot. | Optional: {} |
|
percentOfBudget integer |
PercentOfBudget — 0..200+. | Optional: {} |
|
lastReconciled Time |
LastReconciled timestamp. | Optional: {} |
|
killSwitchFiredAt Time |
KillSwitchFiredAt — non-null once the kill-switch has published a breach event. Firing is not the same as taking effect: the platform is suspended by an out-of-band EventBridge→StepFunctions path, and the reconciler confirms the effect (platform observed Suspended) before it treats the switch as done. See KillSwitchRefireCount and the KillSwitchUnrouted condition. |
Optional: {} |
|
killSwitchRefireCount integer |
KillSwitchRefireCount is how many times the breach event has been re-published because the platform was not observed Suspended within the grace window. Bounded — after the cap the reconciler stops re-publishing but keeps the KillSwitchUnrouted condition set so the alert stays lit. |
Optional: {} |
|
killSwitchLastRefireAt Time |
KillSwitchLastRefireAt is the timestamp of the most recent re-publish. It anchors the exponential backoff between re-fires. |
Optional: {} |
|
conditions Condition array |
Optional: {} |
EvalCase is a single test case. The assertion fields it sets determine its kind — the runner has no separate discriminator:
- Golden case: sets ExpectContains (and optionally MaxLatencyMs / MaxCostUsd). Passes when the agent's output contains every listed substring and stays within the latency/cost ceilings.
- Adversarial / injection case: sets ExpectNotContains and/or ExpectRefusal. Passes when the output leaks none of the forbidden substrings and — when ExpectRefusal is set — the agent declined (a guardrail intervened, or the output matched a refusal).
A case may combine both families (e.g. a jailbreak attempt that must be refused AND must not echo a secret). All assertions present must hold.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
|||
input string |
|||
expectContains string array |
ExpectContains: the output must contain every one of these substrings (golden / positive assertion). Empty = no positive-content assertion. |
Optional: {} |
|
expectNotContains string array |
ExpectNotContains: the output must contain none of these substrings (adversarial / data-leak assertion — e.g. a secret, PII, or a phrase that would indicate the agent complied with an injection). Empty = no forbidden-content assertion. |
Optional: {} |
|
expectRefusal boolean |
ExpectRefusal: when true, the case passes only if the agent declined — either the model gateway reported a guardrail intervention, or the output matched a refusal. Use for adversarial prompts that should be blocked rather than answered. |
Optional: {} |
|
maxLatencyMs integer |
MaxLatencyMs: if set (>0), the case fails when the observed round-trip latency exceeds this ceiling. |
Optional: {} |
|
maxCostUsd string |
MaxCostUsd: if set, the case fails when the observed per-call cost exceeds this ceiling. A model with no pricing entry (unpriced) fails this assertion closed rather than passing on a misleading $0. |
Optional: {} |
EvalSuite is a scheduled evaluation run against an AgentFleet's agents.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
governance.nanohype.dev/v1alpha1 |
||
kind string |
EvalSuite |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec EvalSuiteSpec |
|||
status EvalSuiteStatus |
EvalSuiteSpec defines a periodic evaluation run against an AgentFleet.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
platformRef LocalRef |
|||
agentFleetRef LocalRef |
AgentFleetRef targets the fleet whose agents are under test. | ||
schedule string |
Schedule (cron) — when to run the suite. Empty = manual only. | Optional: {} |
|
cases EvalCase array |
Cases is the list of test cases (input prompt + expected criteria). In production these are typically loaded from an S3 manifest; this inline list is for small / dev suites. |
Optional: {} |
|
casesFromManifest string |
CasesFromManifest loads from eval-reports/<platform>/manifests/<name>.jsonin the eval-reports S3 bucket. |
Optional: {} |
|
passThreshold string |
PassThreshold (0..1) is the required mean score for the run to be marked passing. Argo Rollouts AnalysisTemplate consumes this signal. Modeled as a string so reviewers see decimals in kubectl get -o yamlwithout int<->float coercion surprises; pattern enforces 0.0 .. 1.0. |
0.85 | Pattern: ^(0(\.[0-9]+)?|1(\.0+)?)$ |
EvalSuiteStatus reports the latest run.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
lastRunAt Time |
LastRunAt timestamp. | Optional: {} |
|
lastScore string |
LastScore (mean across cases, 0..1). | Optional: {} |
|
lastReportUrl string |
LastReportURL (s3:// URL to the rendered HTML report). | Optional: {} |
|
phase string |
Phase: Pending, Running, Passed, Failed. | Optional: {} |
|
conditions Condition array |
Optional: {} |
Package v1alpha1 contains API Schema definitions for the platform v1alpha1 API group.
AttributionSpec configures per-session human attribution for a Platform. See github.com/nanohype/fab docs/attribution.md for the consumer side.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
operators string array |
Operators is the set of human identities (e.g. email addresses) a session in this Platform may act as. Each value becomes both an allowed STS SourceIdentity on the session role's trust policy and a resourceNames entry on the impersonate ClusterRole, so the SAME string binds the AWS and Kubernetes audit records. Use a canonical form (a lowercased email); it must byte-match the operator's own RBAC subject name. |
MinItems: 1 |
|
sessionRoleMaxDurationSeconds integer |
SessionRoleMaxDurationSeconds caps the assumed session lifetime. Because the caller is the tenant IRSA role, AWS STS role chaining hard-caps a chained session at 3600s regardless of this value; larger values only matter if the caller ever changes. Defaults to 3600. |
3600 | Maximum: 43200 Minimum: 900 Optional: {} |
BudgetRef points at a BudgetPolicy by name.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
ComplianceSpec enables stricter defaults.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
hipaa boolean |
HIPAA: object-lock compliance mode, no cross-region inference, PII detect required on Guardrails. |
Optional: {} |
|
soc2 boolean |
SOC2: invocation logging required, kill-switch enabled. | Optional: {} |
ContactSpec carries owner / on-call / billing reach paths.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
slackChannel string |
SlackChannel for tenant-wide notifications (e.g. "#acme-ops"). | Optional: {} |
|
oncallRotation string |
OncallRotation — Pagerduty schedule key or similar identifier. | Optional: {} |
|
billingEmail string |
BillingEmail — invoice + budget-breach notification recipient. | Optional: {} |
IdentitySpec wires the per-Platform IRSA role. The controller reconciles a
bedrock-model-scoping inline policy onto the tenant role (and the
attribution session role, when spec.attribution is set) that denies the
Bedrock model-invoke actions (InvokeModel, InvokeModelWithResponseStream,
Converse, ConverseStream) on every resource outside the set that
AllowedModels / AllowedModelFamilies expand to. The baseline policy's broad
invoke grant is thereby narrowed to exactly the declared models; when
neither field is set the policy denies all model invocation
(deny-by-default).
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
allowedModels string array |
AllowedModels is the list of Bedrock model IDs or cross-region inference-profile IDs (e.g. "anthropic.claude-sonnet-4-6", "us.anthropic.claude-sonnet-4-6-v1:0") the role may invoke. The controller expands each entry into its foundation-model ARN pattern plus the matching inference-profile ARN pattern (a us. profile fans out tofoundation models across regions, so both are granted together) and reconciles them into the role's bedrock-model-scoping policy. Scopes tighter than a family; mutually exclusive with AllowedModelFamilies. |
Optional: {} |
|
allowedModelFamilies string array |
AllowedModelFamilies (e.g. ["anthropic", "amazon-nova"]) is expanded by the controller at reconcile time into the family's foundation-model ARN pattern (arn::bedrock:::foundation-model/) and, for families with cross-region inference profiles (anthropic, amazon-nova, meta, mistral), the us. inference-profile ARN pattern(arn::bedrock:::inference-profile/us.*), then reconciled into the role's bedrock-model-scoping policy. Leaving both this and AllowedModels empty denies all Bedrock model invocation for the Platform's roles. |
items:Enum: [anthropic amazon-nova amazon-titan meta mistral cohere stability] Optional: {} |
|
extraPolicyArns string array |
ExtraPolicyArns are managed IAM policies attached on top of the baseline. | Optional: {} |
Platform is the top-level tenancy CR. Namespaced so that BudgetPolicy, ModelGateway, AgentFleet, and EvalSuite references resolve in the same namespace by name. The operator provisions the tenant workload namespace (tenants-) separately at reconcile time; the Platform CR itself lives in whichever namespace the cluster admin places it (typically a management namespace such as eks-agent-platform).
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
platform.nanohype.dev/v1alpha1 |
||
kind string |
Platform |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec PlatformSpec |
|||
status PlatformStatus |
PlatformSpec defines the desired state of a Platform — a tenancy boundary hosting one or more AgentFleets, with its own budget, identity, and guardrails.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
displayName string |
DisplayName is a human-readable name for dashboards and CLI output. | Optional: {} |
|
persona string |
Persona drives default values for AgentFleet, ModelGateway, and dashboards. One of: sales-ops, support, finance, ops, founder, eng, marketing, legal, generic. |
generic | Enum: [sales-ops support finance ops founder eng marketing legal generic] |
tenant string |
Tenant is the owning Tenant CR (one Tenant can own multiple Platforms). | ||
budget BudgetRef |
Budget references a BudgetPolicy CR in the same namespace. | ||
identity IdentitySpec |
Identity controls how the IRSA role is named + which Bedrock models are reachable. |
||
compliance ComplianceSpec |
Compliance flags drive stricter defaults across the Platform. | Optional: {} |
|
isolation string |
Isolation is the workload-isolation tier: - namespace (default): namespace RBAC + default-deny NetworkPolicy + ResourceQuota + PSS-restricted, tenant workloads on the host API server. - vcluster: the same host-side containment PLUS a per-Platform virtual cluster, so tenant code that talks to the Kubernetes API talks to its own API server, not the host's (API-server-level isolation — NOT kernel/node isolation; see docs/adr/0009-vcluster-isolation-tier.md and SECURITY.md). Immutable: switching tiers on a live Platform is a migration (it would strand the virtual cluster and its synced host objects), so the tier is fixed at create time. Re-declare the Platform to change it. Enforced at admission by the CEL transition rule below — an invalid tier flip fails the apply rather than silently half-reconciling. |
namespace | Enum: [namespace vcluster] Optional: {} |
attribution AttributionSpec |
Attribution opts the Platform into per-session human attribution. When set, the operator provisions a session role — assumable by the tenant IRSA role with the operator carried as STS SourceIdentity, scoped to the tenant baseline (Bedrock invoke) and NOT broad sts:AssumeRole — plus a ClusterRole letting the tenant ServiceAccount impersonate the named operators at the apiserver. fab's role-session entrypoint consumes both, so an agent's AWS + Kubernetes actions attribute to a named human. nil = unattributed (the default). |
Optional: {} |
PlatformStatus captures the controller's view of the world.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Provisioning, Ready, Suspended, Failed. | Optional: {} |
|
iamRoleArn string |
IamRoleArn is the per-Platform IRSA role created by the controller. | Optional: {} |
|
sessionRoleArn string |
SessionRoleArn is the per-Platform attribution session role, created when spec.attribution is set. Empty when attribution is off. |
Optional: {} |
|
namespace string |
Namespace is the tenant namespace the controller provisioned. | Optional: {} |
|
observedGeneration integer |
ObservedGeneration is the last spec.generation the controller reconciled. | Optional: {} |
|
suspendedAt Time |
SuspendedAt is the timestamp at which the kill-switch fired. When non-nil the operator stops reattaching the baseline IAM policy and the AgentFleetReconciler scales fleets to zero. Resets to nil only when ops clears the iam:TagRole 'platform.nanohype.dev/suspended' marker on the tenant IRSA role. |
Optional: {} |
|
suspendedReason string |
SuspendedReason carries the kill-switch's reason (e.g. 'budget-exceeded'). Same lifecycle as SuspendedAt. |
Optional: {} |
|
conditions Condition array |
Conditions follows the standard kubernetes pattern. | Optional: {} |
Tenant is the cluster-scoped organizational owner of one or more Platforms. Provides aggregate budget / readiness / suspension views and a single point for non-technical persona dashboards to land on.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
platform.nanohype.dev/v1alpha1 |
||
kind string |
Tenant |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec TenantSpec |
|||
status TenantStatus |
TenantSpec describes an organization (or sub-org) that owns one or more
Platforms. Tenant is cluster-scoped — it doesn't represent a Kubernetes
namespace; it represents an organizational boundary that crosses
Platforms. The relationship to Platform is by Platform.spec.tenant
referencing Tenant.metadata.name.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
displayName string |
DisplayName is the human-readable tenant name shown in dashboards and persona UX. |
Optional: {} |
|
primaryPersona string |
PrimaryPersona drives default values for new Platforms onboarded into this tenant. One of the standard persona names. |
generic | Enum: [sales-ops support finance ops founder eng marketing legal generic] |
contact ContactSpec |
Contact carries human-readable owner info (Slack channel, on-call rotation, billing email) for ops to reach. |
Optional: {} |
|
compliance ComplianceSpec |
Compliance baseline applied to every Platform owned by this Tenant unless the Platform itself sets a stricter value. |
Optional: {} |
|
aggregateMonthlyBudgetUsd string |
AggregateMonthlyBudgetUsd is the soft cap on the SUM of all owned Platforms' BudgetPolicy.spec.monthlyUsd. Status reports whether the sum exceeds this; the operator does not enforce — each Platform's own BudgetPolicy is the enforcement layer. Modeled as a decimal- string to mirror BudgetPolicy.monthlyUsd. |
Pattern: ^[0-9]+(\.[0-9]\{1,2\})?$ Optional: {} |
TenantStatus aggregates the state of Platforms owned by this Tenant.
Appears in:
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase: Pending, Active, Suspended (any owned Platform suspended), Failed. |
Optional: {} |
|
platformCount integer |
PlatformCount is the number of Platform CRs whose spec.tenant == Tenant.metadata.name. |
Optional: {} |
|
readyPlatformCount integer |
ReadyPlatformCount is the subset of PlatformCount in phase=Ready. | Optional: {} |
|
suspendedPlatformCount integer |
SuspendedPlatformCount is the subset in phase=Suspended. | Optional: {} |
|
aggregateSpendUsd string |
AggregateSpendUsd is the sum of CurrentSpendUsd across all owned BudgetPolicies (one per owned Platform). |
Optional: {} |
|
aggregateBudgetUsd string |
AggregateBudgetUsd is the sum of MonthlyUsd across all owned BudgetPolicies. |
Optional: {} |
|
percentOfBudget integer |
PercentOfBudget — 0..200+. Computed from AggregateSpend / AggregateBudget. When > 100 a TenantBudgetExceeded condition fires. |
Optional: {} |
|
lastReconciled Time |
LastReconciled timestamp. | Optional: {} |
|
conditions Condition array |
Optional: {} |