Resource Relationships
Ark resources are Kubernetes objects that reference each other by name. The controller resolves those references during reconciliation and rejects invalid ones through admission webhooks. This page maps the references between resource types, the resources Ark creates for you, and the namespace and validation limits that constrain them.
For how a request actually runs, see Query Execution Flow. For each resource’s fields, see Resources.
Dependency map
Solid arrows are references you author; ==> marks resources the controller creates automatically; dotted arrows are optional or conditional references.
References by resource
| Resource | References | Referenced by |
|---|---|---|
| Query | target or selector → Agent / Team / Model / Tool; memory → Memory | — (created by users, the API, or the dashboard) |
| Agent | modelRef → Model; tools[] → Tool; executionEngine → ExecutionEngine | Query (target), Team (members), Tool (type: agent) |
| Team | members[] → Agent or Team; selector.agent → Agent | Query (target), Team (nested members), Tool (type: team) |
| Model | credentials via Secret / ConfigMap (valueFrom) | Agent (modelRef), Query (target) |
| Tool | mcp → MCPServer; agent → Agent; team → Team (per type) | Agent (tools[]), Query (target) |
| MCPServer | address + credentials via Secret / ConfigMap | Tool (type: mcp) — created for each discovered tool |
| Memory | address (the backing store, e.g. the broker) | Query (memory) |
| A2AServer | address of a remote A2A server | A2ATask (a2aServerRef) |
| A2ATask | queryRef → Query; a2aServerRef → A2AServer; agentRef → Agent | — (created by the controller) |
| ExecutionEngine | address of the engine (A2A) | Agent (executionEngine) |
Note that an Agent does not reference Memory — conversation history is attached to the Query (spec.memory) and resolved by the execution engine at run time.
Resources Ark creates for you
Two controllers create resources from a discovered upstream, and own them so they are garbage-collected when the parent is deleted:
- MCPServer → Tools. When an
MCPServerbecomes reachable, its controller discovers the server’s tools and creates aTool(type: mcp) for each, labelled with the server name and owned by theMCPServer. Delete the server and its tools go with it. - A2AServer → Agents. When an
A2AServeris reachable, its controller discovers the remote agents it advertises and creates a localAgentfor each, withexecutionEngine.name: a2aso queries dispatch to the remote server. The agents are owned by theA2AServer. - Query → A2ATask. When a query runs against an A2A-backed agent, an
A2ATasktracks the asynchronous task — it references the originatingQuery, theA2AServerto poll, and theAgent. See A2ATask.
Namespace scope
References resolve within a single namespace unless the reference type carries its own namespace field:
| Reference | Cross-namespace? |
|---|---|
Agent.spec.modelRef | Yes — honours modelRef.namespace (defaults to the agent’s namespace). |
Agent.spec.executionEngine | Yes — honours executionEngine.namespace (except the built-in a2a engine, which needs no resource). |
Query.spec.memory | Yes — honours memory.namespace (resolved by the execution engine). |
Query.spec.target / spec.selector | No — resolved in the query’s namespace. There is no namespace field on a target. |
Team.spec.members[] | No — members must live in the team’s namespace. |
Because every resource is namespaced, a namespace acts as a tenant boundary. See Tenant and Namespace Management.
Limitations and constraints
The admission webhooks reject relationships that can’t work, so most problems surface at kubectl apply time rather than at run time:
- Query targets exactly one thing. Set either
spec.targetorspec.selector, not both and not neither. Aselectorresolves to the first matching resource (checked Agent → Team → Model → Tool) — it is not a fan-out across matches. - Query targets are same-namespace. The named target (or selector match) must exist in the query’s namespace.
- Teams can’t mix execution engines. All agent members must be either internal (no
executionEngine, or the built-ina2aengine) or external (a named engine) — a team can’t contain both. - Teams can’t reference themselves. A member can’t share the team’s own name; nested teams (
members[].type: team) are allowed otherwise. - Deprecated team strategies are migrated.
round-robinand standalonegraphare accepted but rewritten by the mutating webhook (round-robin→sequentialwith loops;graph→sequential, with the graph edges discarded). Author new teams withsequentialorselector. See Teams. - Missing dependencies block readiness. If a referenced Model, Tool, or engine doesn’t exist, the dependent resource’s
Availablecondition staysFalsewith a reason such asModelNotFound, and flips toTrueautomatically once the dependency appears.
status:
conditions:
- type: Available
status: "False"
reason: ModelNotFound
message: "Model 'gpt-4o' is not available"Creating and deleting related resources
You don’t have to create resources in a strict order — a dependent resource simply stays Available: False until its dependencies exist, then reconciles automatically. A natural order that avoids transient warnings:
- Secrets — API keys and credentials.
- Models — reference their secrets.
- Memory, Tools, MCPServers, ExecutionEngines — supporting resources.
- Agents — reference models, tools, and engines.
- Teams — reference agents (and nested teams).
- A2AServers — discovered agents appear as new
Agentresources.
For deletion, controller-created resources (Tools from an MCPServer, Agents from an A2AServer) are removed automatically with their parent via owner references. Deleting a Query triggers a finalizer that also removes the messages it wrote to its Memory backend — see Query → Deletion and cleanup.
kubectl describe agent weather-agent # spec, status conditions, and events
kubectl get models # AVAILABLE column reflects health probes
ark teams # list teams via the CLIRelated
- Query Execution Flow — how a query runs end to end.
- Resources — every CRD, field by field.
- Core Architecture — the services behind these resources.