Configuration reference
Every record of the organisation specification, with defaults, validation rules and the provider's computed attributes.
The same schema is used everywhere: in Terraform's typed spec attribute, in the AgentOrganization CRD, and in the controller. One compiler validates it at terraform plan time and again in the controller, so the two can never disagree. Field names are snake_case. Map keys are stable keys matching ^[a-z][a-z0-9_]{0,62}$.
Provider
provider "steadmesh" {
kubeconfig_path = "~/.kube/config" # optional; standard loading rules otherwise
kube_context = "kind-steadmesh" # required; the ambient context is never used
namespace = "steadmesh-example" # required; the organisation namespace
}
The provider fails early if the cluster does not serve steadmesh.io/v1alpha1, which means the platform stage has not been applied.
Resource steadmesh_organization
| Attribute | Kind | Description |
key | required | Stable organisation key, 1–40 characters. It is also the object name. Changing it means a new organisation. |
display_name | required | Human-readable name. |
spec | required | The organisation records described below. |
data_retention | optional, default retain | retain or delete: what happens to volumes and records when the organisation is destroyed. |
wait_for_ready | optional, default true | Create and update wait for OperationalReady on the current generation. |
timeouts | block | create, update, delete, default 20m. A timeout keeps state and never cleans up. |
id | computed | Immutable organisation ID. |
manifest_digest | computed at plan time | Digest of the resolved organisation. A change in it without a config change means drift. |
resolved_seats | computed at plan time | Per seat: config_revision, teams, harness_profile and the resolved role_ref. |
conditions | computed | Readiness conditions: type, status, reason, message. |
effective_revision | computed | The revision the controller has adopted. |
connection_details | computed | organization_id, namespace, status_endpoint, and representatives (seat, connection, adapter, external user, mode). Contains no secrets. |
Import. terraform import steadmesh_organization.this <namespace>/<key>. Objects managed by Helm are rejected. An object with no owner annotation needs explicit adoption: <namespace>/<key>/adopt.
Spec records
culture_refs
A list of instruction references applied to every seat, first.
Reference formats
| Kind | Format |
| Instruction | configmap:<name>/<key>#sha256:<hex>, where the ConfigMap is in the organisation namespace, or https://…#sha256:<hex>. The digest is required and is checked before use. The instruction-bundle module produces these. |
| Secret | k8s:<secret-name> (a Secret in the control-plane namespace) or vault:<path> (Vault KV v2). Raw credentials are rejected. |
| Subject | seat:<key> or team:<key> |
| Resource | connection:<key>, memory:<key> or workspace:<key> |
team_templates
| Field | Description |
extends | Another template key. Cycles are rejected. |
instruction_refs | Ordered. They are concatenated after the parent's, and duplicates keep their first position. |
roles | Map of role name to instruction reference. Seats select one with role_ref = "role:<name>". A derived template overrides the parent. |
shared_memory | Map of memory store to operations, granted to the members of teams using this template. The same key with different operations in parent and child is rejected as ambiguous. |
parameters | Map of strings. A derived template overrides the parent. |
Templates are resolved by the provider. The object written to Kubernetes contains only concrete teams.
teams
| Field | Description |
template | Template to instantiate (optional). |
instruction_refs, shared_memory, parameters | Applied on top of the template, as the most derived layer. |
Teams have no member list. Seats declare their teams.
seats
| Field | Required | Description |
role_ref | yes | An instruction reference, or role:<name> from the seat's team templates. A role defined differently by two of the seat's teams is rejected. |
teams | | Ordered list of team keys. The order sets the order of team instructions. |
harness_profile, execution_profile, sandbox_profile | yes | Profile keys. |
personal_memory | | A memory store owned by this seat. A store can be the personal memory of only one seat, and it cannot be shared with a team. |
workspace | default { persistent = true } | persistent, plus shared: shared workspace keys. Each shared workspace also needs an explicit workspace: grant. |
display_name | default: the key | |
instruction_refs | | Seat-scoped instructions, applied last. |
access_profiles | | Access profiles granted to the seat, in addition to its teams' (Sandbox access). |
adopt_from | | The ID of a retired seat whose retained data this seat explicitly adopts. |
memory_stores
| Field | Default | Description |
retention | retain | retain or delete |
backing_class | postgres | The only supported value in this release. |
capacity_mb | | Declared capacity (informational). |
shared_workspaces
Fields: access_mode (required; ReadWriteMany or ReadOnlyMany, which the storage class must support), storage_class, size_gb (default 5) and retention. Declaring and granting shared workspaces is validated, but mounting them into seats is not implemented yet in this release.
harness_profiles
| Field | Description |
adapter | claude-code, codex, pi or fake. See Harnesses and models. |
image_digest | Required. The seat image; pin image@sha256:… in production. |
model | Required for every adapter except fake. An object:
connection: a model connection;
id: the model identifier sent to the endpoint. The platform rejects requests from the seat for any other model;
api (optional): anthropic_messages, openai_responses or openai_chat. When unset, the first API the harness speaks that the connection and model also serve is chosen. No overlap is an error naming both lists and the harnesses that would work;
settings (optional): harness model settings, validated per harness: effort (claude-code); reasoning_effort (codex); thinking, context_window, max_tokens, reasoning (pi).
|
required_capabilities | Must be a subset of the adapter's capabilities. claude-code, codex, pi: tools, mcp, event_stream, session_resume, interrupt, application_checkpoint. fake: tools, event_stream, interrupt, application_checkpoint. |
config | Adapter options, for example bare = "false" for the full Claude Code tool set, or interrupt_grace. |
Changing a profile's adapter, model, API or settings changes the seat's configuration revision: the seat reaches a turn boundary and its Pod is replaced. The seat keeps its identity, volume, memory, inbox and handoff. The same harness resumes its native session; a different harness starts a new session from the portable handoff, which the next turn and the console report.
execution_profiles
| Field | Default | Description |
backend | required | kubernetes |
service_class | interactive | interactive or background |
idle_policy | warm_then_stop | warm (always on), warm_then_stop (stop when idle, wake on messages). suspend is rejected: the backend cannot suspend processes. |
idle_timeout | 15m | Duration of at least 1m. |
cpu_request / cpu_limit | 250m / 2 | Kubernetes quantities. The request cannot exceed the limit. |
memory_request / memory_limit | 512Mi / 2Gi | |
workspace_size_gb | 5 | Size of the seat's persistent volume. |
storage_class | cluster default | Storage class of the workspace volume. |
required_features | | Backend features that must be present: warm_idle, application_stop_restore, network_policy, resource_limits, persistent_workspace, runtime_class, non_root, read_only_root, seccomp. |
access_profiles
Practical access from a seat's sandbox, one plugin per field: tools (binaries), egress (hosts), network (rules of cidr, ports, protocol), github (connection, repos, permissions, delivery) and browser (session.connection). Seats and teams name profiles in access_profiles; a seat gets the union of its own and its teams' profiles. See Sandbox access.
sandbox_profiles
| Field | Default | Description |
network_policy_ref | deny_all_except_platform | Ingress is denied. Egress is allowed only to the platform service and DNS. |
filesystem_policy_ref | workspace_only | Read-only image; writable /seat and /tmp only. |
runtime_class | | A RuntimeClass, for example gVisor or Kata. It is verified to exist; otherwise the seat is Blocked. |
required_enforcement | always includes network_policy, non_root, resource_limits | gvisor or microvm require a runtime_class that provides them. A plain container is never treated as a microVM. |
connections
| Field | Description |
adapter | slack or terminal (communication; terminal is chatted with through orgctl chat, and its secret maps each user ID to a token), linear (tracker), github (code host), browser_session (a signed-in browser session), or a model adapter: anthropic, openai, or model for any compatible endpoint |
secret_ref | Required. Expected keys: Slack bot_token, app_token; Linear api_key; model connections api_key; GitHub app_id, installation_id, private_key (an App) or token (a PAT); browser_session storage_state. |
account_id | The authorised account: the Slack team ID (checked against auth.test), or the Linear organisation ID or URL key. |
endpoint_ref | Base URL override, for fakes or self-hosted endpoints. For model connections it is the API base, usually ending in /v1: https://api.openai.com/v1, https://api.anthropic.com/v1. Required for the model adapter. |
model | Model connections only. apis: the APIs the endpoint serves (defaults: anthropic anthropic_messages; openai openai_responses, openai_chat; required for model). auth: bearer (default; x-api-key for anthropic) or header:<Name>. models: a list of {id, apis}; when set, profiles may only select these. verify: how readiness checks the claims: request (default; a minimal request for each declared model and API and each one a profile uses, trusted for 6 hours once it succeeds), models (list models) or none. |
config | Adapter options. For Linear, team_id is the default team. |
required | Whether the organisation is not ready until this connection authenticates. By default it is decided by role: model connections a harness uses, and communication connections with channel bindings, are required. Others, such as a work tracker, are optional. A failing optional connection is reported in the IntegrationsDegraded condition and never blocks readiness or internal work. |
ownership | external (default): never deleted by the platform. managed is rejected in this release. |
Operations a grant can name: Slack channel.reply (normally implicit through bindings); Linear project.read, project.create, task.read, task.write, comment.write; model connections model.infer (normally implicit through the harness).
grants
| Field | Description |
subject | seat:<key> or team:<key>. Team grants apply to the team's members at each policy revision. |
resource | connection:, memory: or workspace: plus a key. |
operations | Memory: read, search, write, revise, archive, publish, history. Workspace: read, write. Connection: the adapter's operations. |
targets | Optional restriction on targets: exact values, *, or a prefix*. The target is read from the operation's target, project_id, team_id or issue_id parameter. |
Only three permissions are implicit: a seat's own personal_memory (all memory operations), model.infer on its harness's model connection, and channel.reply to the human it is bound to. Each appears in the seat's capability manifest with an implicit: source.
message_routes
| Field | Description |
from, to | Seat or team subjects. A team expands to its members, and a seat never routes to itself. |
reply | The recipient may reply within conversations opened on this route. |
bidirectional | Both directions, each with reply. |
channel_bindings
| Field | Description |
connection | A communication connection. |
external_user_id | The verified external user, for example a Slack member ID. One identity can be bound only once. |
seat | The representative. A seat can represent only one human. |
mode | direct_message (the default and only mode). |
work_publication (optional)
Publishes the work items of shared memory stores to a tracker, so people can follow progress there. Agents coordinate in memory and messages either way. They can also use the tracker directly through connections.invoke whenever they are granted it, independently of publication.
| Field | Description |
connection | A tracker connection, for example Linear. |
stores | Shared memory stores whose work items are published. Personal stores are rejected, so private memory is never published. |
Each work item becomes one issue, titled <store>/W-<n>: <objective>, with its status, owner, plan, acceptance criteria and evidence in the description. Later changes update the same issue. Publication runs in the background and is retried while the tracker is unavailable. Its state is shown per item in the console's Work view, separately from the work itself. A crash between creating an issue and recording it is resolved by reading the issue back, never by creating a duplicate. This is outward only: edits made in the tracker do not change work items, although agents can read them with task.read and comment.read.
Limits
- The serialised specification is limited to 256 KiB. Reference large documents by digest instead of inlining them.
- Seat object names are derived deterministically and kept short enough for Kubernetes:
seat-<key>-<8 hex>.
- The defaults above belong to
defaults_version = 1, which is recorded in every effective manifest.
Modules
| Module | Inputs | Outputs |
modules/instruction-bundle | name, namespace, source_path | ref |
modules/team-base | namespace | template_key, team_templates |
modules/team-engineering | namespace, extends, shared_memory, extra_roles, extra_instruction_refs, parameters, template_key | template_key, team_templates (roles engineering_lead, engineer, reviewer) |
modules/team-accounting | as above | an accounting specialisation of base |
modules/representative | human, external_user_id, role_ref, connection, display_name, profile keys, seat_key, memory_store_key, memory_retention | seat_key, seats, memory_stores, channel_bindings (seat representative_<human>, store rep_<human>) |