Agent architecture¶
Astrolift's agent support is part of the main control plane. It is not a separate product or a set of optional Django applications. Agent definitions, skills, environment recipes, tasks, workflows, secrets, and dispatch records share the platform's organization, project, permission, and audit boundaries.
This page describes the code that runs today. The public CLI and API reference remain the source of truth for command syntax and wire contracts.
The objects that make up an agent¶
An agent is assembled from several independently managed objects:
| Object | Purpose |
|---|---|
RegisteredApp + Workload(kind="agent") |
Registered agent identity, source repository, image, run policy, and deployment metadata |
AgentEnvironmentSpec |
Reusable image/runtime recipe, tool preset, install policy, VNC choice, managed-model choice, environment variables, and secret references |
Skill |
Versioned instructions and dependency metadata; global skills are readable by every organization and organization skills remain tenant-scoped |
ToolDef |
Callable tool metadata for a skill: Python function, HTTP endpoint, or MCP server |
Brief |
Immutable, content-hashed snapshot assembled for one definition or dispatch |
AgentTask |
One dispatch and its lifecycle, runtime location, callback identity, result, failure, and telemetry pointers |
AgentRun |
Fleet/run history associated with a workload; newer dispatches link it directly to their AgentTask |
DispatcherInstance |
Registered execution endpoint and its cloud, region, backend, capabilities, and heartbeat |
This split is intentional. Updating a skill or environment recipe does not rewrite historical tasks: a task uses a frozen Brief and stores the environment recipe and source reference selected for that run.
Repository definitions¶
The ordinary source of an agent definition is astrolift.toml. A repository
may contain one agent at its root or many independently registered agents below
different paths. An environment spec's config_manifest_path selects either a
particular manifest or a directory whose astrolift.toml is authoritative.
Registration turns an agent workload into database objects and resolves its
skill and tool references. Repository-owned files may supply prompts, scripts,
and other assets without pasting them into a single TOML string; path resolution
is constrained to the selected manifest tree. Imported skill repositories are
represented by OrgSkillRepo and use a source connection for private GitHub
access.
The declarative manifest is the desired configuration. Secret values are not declarative repository content. Manifests and environment specs contain secret references; the dispatcher resolves values at launch.
Brief assembly¶
A Brief is the hand-off between definition and execution. Assembly combines:
- the registered workload and source manifest snapshot;
- resolved environment variables and dispatch input;
- selected skills and their versions;
- tool definitions and install metadata;
- secret references, never plaintext secret values; and
- organization, project, workflow, and source context.
The canonical JSON payload is SHA-256 addressed and stored under an object-store key. A READY Brief can therefore be reused when its content is identical. A change creates a new Brief rather than mutating the package used by an existing task. Briefs can also expire or be revoked.
Dispatch lifecycle¶
The platform creates an AgentTask, prepares its Brief, and starts a durable
Temporal dispatch workflow. Its states are:
DRAFT -> QUEUED -> PROVISIONING -> RUNNING
| | | |
+--------+------------+------------+-> CANCELLED
+------------+------------+-> FAILED
+------------+-> TIMED_OUT
+-> COMPLETED
The managed Kubernetes path creates a per-dispatch Job in an organization
namespace. It resolves the target tenant cluster, materializes launch secrets in
a Kubernetes Secret, injects task and callback metadata, and polls the Job until
a terminal state. The terminal path cleans up the per-task secret. A configured
timeout becomes the Job's activeDeadlineSeconds as well as a control-plane
timeout.
Cancellation is an execution operation, not merely a database update. For a
provisioning or running Kubernetes task, Astrolift deletes the Job and its pod
before marking the task cancelled. Operators can use astro agent cancel for
runaway tasks; see the operator runbooks.
K8sJobSpawner is the managed production spawner. A local Docker spawner also
exists for development. DispatcherInstance and the
/api/dispatch/v1/ controller endpoints support registered external dispatch
processes, but the managed Temporal activity currently selects the Kubernetes
Job spawner for cluster-backed tasks. Do not infer that every backend value on
DispatcherInstance is implemented by that managed activity.
Container contract and callbacks¶
The injector supplies the task's runtime contract, including task/organization
identity, input, prompt and Brief context. A valid externally reachable
PLATFORM_API_URL is required to construct:
AGENT_CALLBACK_URL;AGENT_CALLBACK_TOKEN; and- the log, meter, and check-in endpoints used by the running container.
The callback token is short-lived and task-scoped; only its SHA-256 hash is stored. A terminal transition clears that hash. The agent callback endpoint persists the result and interactions and then advances the task. Tooling must not report a callback as successful if no callback URL was injected; that is a configuration failure, not a successful no-op.
The controller REST surface is mounted by the main Django application at
/api/dispatch/v1/. It may be used by a separately deployed dispatcher, but it
does not require a separate control-plane service in the standard deployment.
Logs, terminal, and VNC¶
Kubernetes pod stdout/stderr is the source used by astro agent logs. A
terminal or noVNC session is a separate stream. An image that directs only its
Xvnc supervisor to stdout can therefore show Xvnc messages in pod logs while an
attached terminal displays application output. Agent images should send the
actual runtime's stdout and stderr to the container streams as well as any
interactive terminal.
When an environment recipe enables VNC, the task records a relay URL after it
enters RUNNING. The ASGI application relays raw RFB traffic at
/app/vnc/<task-guid> and can expose the latest uploaded JPEG snapshot. The old
HTTP/WSGI VNC proxy no longer exists.
Environments, tools, and managed models¶
AgentEnvironmentSpec.image_tag takes precedence over its runtime catalogue
name. When no explicit image is supplied, the runtime catalogue resolves a
canonical Astrolift agent image; an empty runtime falls back to the workload's
image.
The recipe also controls tool_preset, allow_install, VNC, and
managed_model. These fields are launch inputs, not documentation-only
metadata. Tool definitions can bind to specific agent runtimes, declare command
and package requirements, and indicate whether they are already in the image.
Install-at-run behavior still depends on the selected image and policy; allowing
installation does not grant arbitrary platform permissions.
With managed_model=true, the cluster driver supplies cloud-native model
identity and provider environment instead of requiring a long-lived model API
key. AWS uses Bedrock and GCP uses Vertex. Model identifiers should remain
operator-configurable because cloud providers can retire models independently
of IAM policy changes.
Secrets¶
There are three related layers:
- an organization/app secret value in a configured secrets backend;
- a reference or bundle attached to an agent/environment; and
- the short-lived Kubernetes Secret materialized for a task.
Secret access is permission-checked and API-token scopes are an additional
ceiling over a user's RBAC grants. Being an organization administrator does not
make a read-only device token capable of secret.write or agent.dispatch.
Use a token carrying the required narrow scope, and remember that revealing a
value also depends on the backing provider's reveal capability.
Agent workflows¶
WorkflowDefinition is the reusable workflow template and
WorkflowStage is its ordered execution plan. Agent pipelines normally leave
model_label blank: that field is a legacy Django content-object target, not
an LLM model or an agent selector.
For an agent stage:
agentselects the registered agent workload by local slug;environment_spec_slugoptionally overrides the agent's environment recipe;skillsadds local, catalogue, or organization-repository skill references;promptadds instructions for this stage; andoutput_keynames the stage result in the workflow's accumulated output map.
Ordered stages are the executable pipeline. The legacy states and
transitions JSON fields still serve content-object state machines; they do not
need to be invented for a declarative agent pipeline. A chained workflow passes
each stage's result into the next stage and also stores it under the unique
output_key. Human-gate stages pause the Temporal workflow until approval or
rejection.
Workflow manifests use a [workflow] table followed by ordered [[stage]]
tables. They can be bundled in Astrolift's catalogue or reconciled from a
connected repository. See the generated CLI/config reference for the exact
schema accepted by the installed release.
Tenant and trust boundaries¶
- Definitions, environment recipes, tasks, dispatchers, secret bindings, and organization skills are organization-scoped.
- Platform-global skills and workflow templates are readable by tenants but writable only by platform operators.
- Dispatch lookup verifies workload kind, run family, organization, and permissions before preparing a task.
- Repository sync is bound to the connected source identity and configured path.
- Callback, deploy, API, and MCP tokens each have explicit scopes. A bearer token never inherits permissions outside its own scope ceiling.
- Values stay in a secrets backend until launch and are not persisted in a Brief or repository manifest.
These boundaries must hold on every entry point: dashboard, CLI, GraphQL, REST, MCP, webhooks, schedulers, and workflow activities.