ArkTeam
API: arkonis.dev/v1alpha1
Kind: ArkTeam
Scope: Namespaced
ArkTeam defines a team of agents and how they work together. The execution mode is determined by which fields you set:
| Mode | When | Analogy |
|---|---|---|
| Pipeline | spec.pipeline is set | CI workflow — steps run in DAG order |
| Dynamic | No spec.pipeline, roles use canDelegate | Org chart — agents decide at runtime who to call |
| Mixed | Both set | Pipeline with per-step sub-delegation |
Each time a pipeline ArkTeam is triggered, the operator creates an ArkRun — an immutable execution record that holds step outputs, token usage, and timestamps. The ArkTeam is the template; the ArkRun is what ran.
Quick examples
Pipeline (sequential DAG)
apiVersion: arkonis.dev/v1alpha1
kind: ArkTeam
metadata:
name: blog-pipeline
namespace: my-org
spec:
output: "{{ .steps.editor.output }}"
roles:
- name: researcher
model: llama3.2
systemPrompt: "Research the topic thoroughly."
- name: writer
model: llama3.2
systemPrompt: "Write a blog post from the research."
- name: editor
model: llama3.2
systemPrompt: "Edit and polish the post."
pipeline:
- role: researcher
inputs:
prompt: "{{ .input.topic }}"
- role: writer
dependsOn: [researcher]
inputs:
research: "{{ .steps.researcher.output }}"
- role: editor
dependsOn: [writer]
inputs:
draft: "{{ .steps.writer.output }}"
Dynamic delegation (autonomous team)
apiVersion: arkonis.dev/v1alpha1
kind: ArkTeam
metadata:
name: startup-team
namespace: my-org
spec:
entry: pm
roles:
- name: pm
model: llama3.2
systemPrompt: "You are the PM. Coordinate the team."
canDelegate: [engineer, designer]
- name: engineer
arkAgent: engineer-agent
canDelegate: []
- name: designer
arkAgent: designer-agent
canDelegate: []
Roles
A role is a named position in the team. Each role is exactly one of three types:
A) Inline — the operator auto-creates an ArkAgent named {team}-{role}:
roles:
- name: researcher
model: llama3.2
systemPrompt: "Research the topic thoroughly."
limits:
maxTokensPerCall: 8000
B) Reference to an existing ArkAgent:
roles:
- name: writer
arkAgent: my-writer-agent
C) Reference to another ArkTeam (cross-team composition — pipeline mode only):
roles:
- name: legal-review
arkTeam: legal-team # the entire legal-team runs as a single step
Template expressions
Inputs and outputs are wired together with Go templates. The template context is populated as steps complete.
| Expression | Resolves to |
|---|---|
{{ .input.<key> }} | Value from spec.input or the trigger payload |
{{ .steps.<name>.output }} | Raw output string from a completed pipeline step |
{{ .steps.<name>.data.<field> }} | Typed field from a step with outputSchema |
{{ .roles.<name>.output }} | Output from a dynamic role (dynamic mode only) |
Role names must not contain hyphens — Go templates use .steps.<name> as a field accessor.
Conditional steps
Skip a step based on a previous step’s output:
- role: escalate
dependsOn: [triage]
if: "{{ .steps.triage.data.severity }}"
inputs:
issue: "{{ .steps.triage.output }}"
Loop steps
Repeat a step until a condition is met (or max iterations is reached):
- role: refine
dependsOn: [draft]
loop:
condition: "{{ not .steps.refine.data.approved }}"
maxIterations: 5
inputs:
draft: "{{ .steps.refine.output }}"
Typed output schemas
Instruct an agent to respond in a specific JSON format. Downstream steps access fields via .data.<field>:
- role: triage
outputSchema: |
{"type":"object","properties":{"severity":{"type":"string"},"summary":{"type":"string"}}}
inputs:
prompt: "Triage: {{ .input.issue }}"
- role: escalate
dependsOn: [triage]
if: "{{ eq .steps.triage.data.severity \"high\" }}"
inputs:
summary: "{{ .steps.triage.data.summary }}"
Run history
Each trigger creates a new ArkRun. Control how many are retained:
spec:
successfulRunsHistoryLimit: 10 # default
failedRunsHistoryLimit: 3 # default
runRetainFor: "168h" # also delete runs older than 7 days
Cross-team composition
# Sub-team handles legal review
apiVersion: arkonis.dev/v1alpha1
kind: ArkTeam
metadata:
name: legal-team
namespace: my-org
spec:
entry: counsel
roles:
- name: counsel
arkAgent: legal-counsel-agent
canDelegate: [paralegal]
- name: paralegal
arkAgent: paralegal-agent
---
# Parent team references legal-team as a step
apiVersion: arkonis.dev/v1alpha1
kind: ArkTeam
metadata:
name: product-team
namespace: my-org
spec:
output: "{{ .steps.legalreview.output }}"
roles:
- name: pm
arkAgent: pm-agent
- name: legalreview
arkTeam: legal-team
pipeline:
- role: pm
inputs:
feature: "{{ .input.feature }}"
- role: legalreview
dependsOn: [pm]
inputs:
document: "{{ .steps.pm.output }}"
Spec reference
spec
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
roles | []RoleSpec | yes | — | Named roles. Each is an inline agent, an ArkAgent ref, or an ArkTeam ref. |
entry | string | dynamic mode | — | Name of the role that receives the initial task. Required when spec.pipeline is absent. |
output | string | no | — | Go template expression producing the team’s final result. |
input | map[string]string | no | — | Default input values used when the team is triggered without explicit input. |
pipeline | []PipelineStep | no | — | DAG steps. Absent = dynamic delegation mode. |
timeoutSeconds | int | no | 0 | Wall-clock timeout for the entire run. Zero means no timeout. |
maxTokens | int | no | 0 | Hard token budget across all roles per run. Zero means no limit. |
limits.maxDailyTokens | int64 | no | 0 | Rolling 24-hour token cap. Scales all role replicas to 0 when hit; auto-resumes when the window rotates. |
successfulRunsHistoryLimit | int32 | no | 10 | Number of successful ArkRun records to retain. |
failedRunsHistoryLimit | int32 | no | 3 | Number of failed ArkRun records to retain. |
runRetainFor | duration | no | — | Maximum age for completed ArkRun records. Example: "168h" (7 days). |
notifyRef | LocalObjectReference | no | — | Name of an ArkNotify policy for team events. |
spec.roles[] — inline role
| Field | Type | Description |
|---|---|---|
name | string | Unique role name within the team. No hyphens — used in template expressions. |
model | string | LLM model ID. |
systemPrompt | string | Inline system prompt. |
systemPromptRef | SystemPromptSource | Reference to a ConfigMap or Secret key. |
mcpServers | []MCPServerSpec | MCP tool servers. Same structure as ArkAgent.spec.mcpServers. |
tools | []WebhookToolSpec | Inline HTTP webhook tools. |
replicas | int | Number of parallel workers on this role’s queue. |
limits | AgentLimits | Per-call token limit, timeout, and concurrency. |
canDelegate | []string | Roles this role may delegate to at runtime. |
spec.roles[] — ArkAgent reference role
| Field | Type | Description |
|---|---|---|
name | string | Unique role name. |
arkAgent | string | Name of an existing ArkAgent in the same namespace. |
canDelegate | []string | Roles this role may delegate to. |
spec.roles[] — ArkTeam reference role
| Field | Type | Description |
|---|---|---|
name | string | Unique role name. |
arkTeam | string | Name of another ArkTeam. The entire sub-team runs as a single step. |
canDelegate values
| Value | Meaning |
|---|---|
omit or [] | Pure worker — no delegate() tool injected. |
["role-a", "role-b"] | Can only delegate to these roles. Validated at deploy time. |
["*"] | Fully autonomous — can delegate to any role in the team. |
spec.pipeline[]
| Field | Type | Required | Description |
|---|---|---|---|
role | string | yes | Name of a role in spec.roles. |
inputs | map[string]string | no | Key-value inputs. Values are Go template expressions. |
dependsOn | []string | no | Step role names that must complete before this step runs. |
if | string | no | Go template expression. Step is skipped when falsy. |
loop | LoopSpec | no | Repeat this step until the condition is false or max iterations reached. |
outputSchema | string | no | JSON Schema (raw string). Enables {{ .steps.<name>.data.<field> }}. |
spec.pipeline[].loop
| Field | Type | Default | Description |
|---|---|---|---|
condition | string | — | Go template expression. Repeats while truthy. |
maxIterations | int | 10 | Hard cap. Range: 1–100. |
status
ArkTeam.status reflects infrastructure state. Step-level execution detail lives on the ArkRun.
| Field | Type | Description |
|---|---|---|
phase | string | Pending | Ready | Running | Succeeded | Failed |
lastRunName | string | Name of the most recently created ArkRun. |
lastRunPhase | string | Phase of the most recent ArkRun. |
roles | []RoleStatus | Infrastructure state per role. |
entryRole | string | Entry role name (dynamic mode). |
serviceName | string | Auto-created ArkService name (dynamic mode). |
observedGeneration | int64 | The .metadata.generation this status reflects. |
conditions | []Condition | Ready. |
status.roles[]
| Field | Type | Description |
|---|---|---|
name | string | Role name. |
readyReplicas | int32 | Agent pods currently passing readiness checks. |
desiredReplicas | int32 | Configured replica count for this role. |
managedArkAgent | string | Name of the auto-created ArkAgent for inline roles. |
See also
- ArkRun — execution records: step outputs, token usage, run history
- ArkNotify — notifications for team events
- Building a Pipeline guide — step-by-step pipeline construction
- Autonomous Delegation example — full dynamic mode example