subagent

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package subagent defines the contract for delegating a bounded sub-task to a nested agent. The in-process implementation (internal/turn) runs an ephemeral turn; the interface is intentionally backend-agnostic so a future Aether-task implementation (spawning a separate sandbox/agent) can satisfy the same contract without changing the spawn tool.

Index

Constants

View Source
const (
	// ExecutionEnvelopeSchema identifies the OSS child-execution descriptor
	// carried by a durable task backend. It is an execution-plane contract, not
	// part of the ecosystem session-message protocol.
	ExecutionEnvelopeSchema = "agent-harness.subagent.execution"
	// Revision 1 includes the exact workspace execution scope. This contract is
	// still unreleased, so iterative local shapes are not retained as separate
	// compatibility revisions.
	ExecutionEnvelopeSchemaRevision = 1

	ExecutionBackendHistory        = "history"
	ExecutionBackendTaskCheckpoint = "task_checkpoint"

	ExecutionArtifactMessage        = "message"
	ExecutionArtifactAssistantAfter = "assistant_after_input"
	ExecutionArtifactCheckpoint     = "checkpoint"

	ExecutionAuthorityDurableTask = "durable_task"
	ExecutionUncertainInterrupt   = "interrupt_without_replay"
)
View Source
const (
	MaxOutputSchemaBytes = 64 << 10
)

Variables

View Source
var (
	ErrInvalidDefinition     = errors.New("subagent: invalid agent definition")
	ErrInvalidPermissionMode = errors.New("subagent: invalid permission mode")
	ErrToolDenied            = errors.New("subagent: tool denied")
)
View Source
var (
	ErrCorruptRegistry  = errors.New("subagent: corrupt lifecycle registry")
	ErrDeletedLifecycle = errors.New("subagent: deleted lifecycle cannot be resumed")
)
View Source
var (
	ErrTaskOutcomeUncertain = errors.New("subagent: execution task outcome is uncertain")
	// ErrParentCheckpointUncertain means child admission may already be durable,
	// but the parent turn could not confirm its own recovery checkpoint. The
	// parent must stop immediately and must not turn this into an ordinary tool
	// error that lets the model request another child.
	ErrParentCheckpointUncertain = errors.New("subagent: parent admission checkpoint is uncertain")
)

ErrTaskOutcomeUncertain means child execution ended locally but the durable task backend could not confirm its terminal transition. Callers must not automatically replay the child: its transcript or tool side effects may have committed even though the task still appears non-terminal.

View Source
var ErrBackgroundUnsupported = errors.New("subagent: background execution not supported")

ErrBackgroundUnsupported is returned when a background spawn is requested but the installed runner does not implement BackgroundRunner (e.g. a backend without a detached-execution seam). The spawn tool treats it as a signal to fall back to a synchronous run rather than failing the call.

View Source
var ErrCASRetryLimit = errors.New("subagent: distributed lifecycle update retry limit exceeded")
View Source
var ErrNoRunner = errors.New("subagent: no runner configured")

ErrNoRunner is returned when a sub-agent is requested but no runner is wired.

View Source
var ErrUnknownAgent = errors.New("subagent: unknown agent")

Functions

func Depth

func Depth(ctx context.Context) int

Depth reports the current sub-agent nesting depth (0 at the top level).

func MarshalExecutionEnvelope added in v0.0.2

func MarshalExecutionEnvelope(envelope ExecutionEnvelope) ([]byte, error)

MarshalExecutionEnvelope validates and deterministically encodes a descriptor for a durable task payload.

func StructuredDigest added in v0.0.2

func StructuredDigest(raw json.RawMessage) string

StructuredDigest identifies the exact validated JSON bytes returned by a child. Callers should trim surrounding whitespace before computing it.

func WithDepth

func WithDepth(ctx context.Context, depth int) context.Context

WithDepth returns a context carrying the sub-agent nesting depth.

Types

type AgentName

type AgentName string

type AgentType

type AgentType string

type AssignedExecutionResolver added in v0.0.2

type AssignedExecutionResolver interface {
	ResolveAssignedExecution(ctx context.Context, workspaceID string) (AssignedExecutionResources, error)
}

AssignedExecutionResolver selects workspace-scoped execution resources for an externally assigned child. Implementations must not fall back across workspace boundaries: a resolution failure prevents model/tool execution and is recorded as a terminal rejection before the task is claimed.

type AssignedExecutionResolverFunc added in v0.0.2

type AssignedExecutionResolverFunc func(context.Context, string) (AssignedExecutionResources, error)

AssignedExecutionResolverFunc adapts a function to AssignedExecutionResolver.

func (AssignedExecutionResolverFunc) ResolveAssignedExecution added in v0.0.2

func (f AssignedExecutionResolverFunc) ResolveAssignedExecution(ctx context.Context, workspaceID string) (AssignedExecutionResources, error)

type AssignedExecutionResources added in v0.0.2

type AssignedExecutionResources struct {
	Runner  AssignedRunner
	Catalog Catalog
}

AssignedExecutionResources are resolved after the executor has validated an envelope's workspace identity and typed task authority, but before it claims the task. A multi-workspace host uses this seam to select a runner and catalog built exclusively for that logical workspace.

type AssignedRunner added in v0.0.2

type AssignedRunner interface {
	ExecuteAssignedSubagent(ctx context.Context, taskID string, envelope ExecutionEnvelope, req Request) (Result, error)
}

AssignedRunner consumes an already-admitted execution. The caller owns the durable task claim and terminal transition; implementations must not admit a second task for the same envelope.

type BackgroundRunner

type BackgroundRunner interface {
	Runner
	StartBackground(ctx context.Context, req Request) (threadID string, err error)
}

BackgroundRunner is a Runner that can additionally start a sub-agent DETACHED: StartBackground mints (or resumes) the child thread, launches the run asynchronously, and returns the child thread id — the re-addressable handle — immediately, without waiting for the child to finish. The backend delivers the child's completion out-of-band (the in-process backend pushes a notice back to the parent thread that wakes a fresh parent turn). A backend that cannot detach need not implement this; the spawn tool falls back to a synchronous RunSubagent.

type CASRegistry added in v0.0.2

type CASRegistry struct {
	// contains filtered or unexported fields
}

CASRegistry persists one bounded-by-parent lifecycle projection per workspace/session. A small CAS-maintained identity index supports startup interruption recovery without requiring backend-specific key scans.

func NewCASRegistry added in v0.0.2

func NewCASRegistry(config CASRegistryConfig) (*CASRegistry, error)

func (*CASRegistry) ListSubagents added in v0.0.2

func (r *CASRegistry) ListSubagents(ctx context.Context, workspaceID, parentSessionID string) ([]spec.SessionSubagentRecord, error)

func (*CASRegistry) ObserveSubagent added in v0.0.2

func (r *CASRegistry) ObserveSubagent(ctx context.Context, event LifecycleEvent) error

func (*CASRegistry) RecoverInterrupted added in v0.0.2

func (r *CASRegistry) RecoverInterrupted(ctx context.Context, at time.Time) error

func (*CASRegistry) RecoverInterruptedWithTasks added in v0.0.2

func (r *CASRegistry) RecoverInterruptedWithTasks(ctx context.Context, at time.Time, tasks TaskBackend) error

RecoverInterruptedWithTasks reconciles unfinished projections against the durable execution task state. In deferred Aether mode the backend is retained with the timestamp and used by the first post-connect registry operation.

type CASRegistryConfig added in v0.0.2

type CASRegistryConfig struct {
	Blobs      casblob.Store
	Prefix     string
	MaxRetries int
	// DeferRecovery makes RecoverInterrupted record the requested recovery and
	// apply it on the first later read/write. Aether workers use this because KV
	// becomes available only after Start; successful connection of their stable
	// agent identity proves the prior duplicate is no longer active.
	DeferRecovery bool
}

type Catalog

type Catalog interface {
	List(ctx context.Context) ([]Definition, error)
	Get(ctx context.Context, typ AgentType) (Definition, error)
}

type Definition

type Definition struct {
	Name           AgentName      `json:"name"`
	Type           AgentType      `json:"type"`
	Description    string         `json:"description"`
	Prompt         string         `json:"prompt,omitempty"`
	PromptPath     string         `json:"prompt_path,omitempty"`
	Model          string         `json:"model,omitempty"`
	MaxTurns       int            `json:"max_turns,omitempty"`
	AllowedTools   []string       `json:"tool_allow,omitempty"`
	DeniedTools    []string       `json:"tool_deny,omitempty"`
	Skills         []string       `json:"skills,omitempty"`
	MCPServers     []string       `json:"mcp_servers,omitempty"`
	PermissionMode PermissionMode `json:"permission_mode,omitempty"`
	ExecPolicyHint string         `json:"exec_policy_hint,omitempty"`
	Background     bool           `json:"background,omitempty"`
}

func (Definition) AllowsTool

func (d Definition) AllowsTool(tool string) error

func (Definition) Validate

func (d Definition) Validate() error

type ExecutionArtifactRef added in v0.0.2

type ExecutionArtifactRef struct {
	Backend     string `json:"backend"`
	Kind        string `json:"kind"`
	WorkspaceID string `json:"workspace_id,omitempty"`
	SessionID   string `json:"session_id,omitempty"`
	RecordID    string `json:"record_id"`
	Digest      string `json:"digest,omitempty"`
}

ExecutionArtifactRef names durable child input, output, or checkpoint state without embedding model-visible text in the task payload. History references are resolved within the explicit workspace/session pair. A checkpoint key is task-scoped by the durable backend.

type ExecutionEnvelope added in v0.0.2

type ExecutionEnvelope struct {
	SchemaRevision     uint32                       `json:"schema_revision"`
	Schema             string                       `json:"schema"`
	ExecutionID        string                       `json:"execution_id"`
	WorkspaceID        string                       `json:"workspace_id"`
	CatalogRevision    string                       `json:"catalog_revision,omitempty"`
	OutputSchema       json.RawMessage              `json:"output_schema,omitempty"`
	OutputSchemaDigest string                       `json:"output_schema_digest,omitempty"`
	ParentSessionID    string                       `json:"parent_session_id"`
	ChildSessionID     string                       `json:"child_session_id"`
	ParentTaskID       string                       `json:"parent_task_id,omitempty"`
	ParentMessageID    string                       `json:"parent_message_id,omitempty"`
	InvocationID       string                       `json:"invocation_id,omitempty"`
	Depth              int                          `json:"depth"`
	Background         bool                         `json:"background,omitempty"`
	ExecutionScope     *workspacepkg.ExecutionScope `json:"execution_scope,omitempty"`
	Input              ExecutionArtifactRef         `json:"input"`
	Result             ExecutionArtifactRef         `json:"result"`
	Checkpoint         ExecutionArtifactRef         `json:"checkpoint"`
	Policy             ExecutionPolicy              `json:"policy"`
	Ownership          ExecutionOwnership           `json:"ownership"`
}

ExecutionEnvelope is the immutable descriptor for one child invocation. It contains references and hashes, never the delegated task text, catalog instructions, or authority credentials. A backend may carry the encoded envelope as its task payload while retaining ordinary metadata for indexing.

func NewExecutionEnvelope added in v0.0.2

func NewExecutionEnvelope(req Request, workspaceID, childSessionID string, background bool) (ExecutionEnvelope, error)

NewExecutionEnvelope builds the immutable descriptor used by both the local in-process executor and optional durable task backends.

func ParseExecutionEnvelope added in v0.0.2

func ParseExecutionEnvelope(data []byte) (ExecutionEnvelope, error)

ParseExecutionEnvelope strictly decodes one descriptor. Unknown fields and trailing JSON are rejected so executors cannot silently disagree on policy.

func (ExecutionEnvelope) ExecutionScopeDigest added in v0.0.2

func (e ExecutionEnvelope) ExecutionScopeDigest() string

ExecutionScopeDigest is a stable, credential-free correlation value for task metadata. The complete scope remains in the versioned payload.

func (ExecutionEnvelope) ResolveInput added in v0.0.2

func (e ExecutionEnvelope) ResolveInput(messages []protocol.ChatMessage) (protocol.ChatMessage, string, error)

ResolveInput finds and verifies the referenced user message, returning the exact task text an executor should run. Duplicate record IDs fail closed.

func (ExecutionEnvelope) ResolveResult added in v0.0.2

func (e ExecutionEnvelope) ResolveResult(messages []protocol.ChatMessage) (protocol.ChatMessage, error)

ResolveResult returns the first terminal assistant message after the exact referenced input. Assistant messages that contain tool calls are intermediate execution state and are skipped. A later execution input bounds the search so resuming the same child session cannot replace an earlier result.

func (ExecutionEnvelope) Validate added in v0.0.2

func (e ExecutionEnvelope) Validate() error

Validate checks identity, workspace isolation, artifact shape, and ownership invariants without resolving any referenced content.

func (ExecutionEnvelope) VerifyPolicy added in v0.0.2

func (e ExecutionEnvelope) VerifyPolicy(req Request) error

VerifyPolicy proves that req is the same immutable policy snapshot described by the envelope. It includes catalog instructions in the digest even though those instructions are not serialized into the envelope.

type ExecutionOwnership added in v0.0.2

type ExecutionOwnership struct {
	Authority       string `json:"authority"`
	ClaimRequired   bool   `json:"claim_required"`
	MaxAttempts     uint32 `json:"max_attempts"`
	UncertainPolicy string `json:"uncertain_policy"`
}

ExecutionOwnership makes the task/executor boundary explicit. The first successful durable-task claim owns execution. One attempt is allowed; an uncertain outcome is interrupted and inspected rather than replayed.

type ExecutionPolicy added in v0.0.2

type ExecutionPolicy struct {
	AgentName      string   `json:"agent_name,omitempty"`
	AgentType      string   `json:"agent_type,omitempty"`
	Model          string   `json:"model,omitempty"`
	MaxTurns       int      `json:"max_turns,omitempty"`
	AllowedTools   []string `json:"allowed_tools,omitempty"`
	DeniedTools    []string `json:"denied_tools,omitempty"`
	Skills         []string `json:"skills,omitempty"`
	MCPServers     []string `json:"mcp_servers,omitempty"`
	PermissionMode string   `json:"permission_mode,omitempty"`
	ExecPolicyHint string   `json:"exec_policy_hint,omitempty"`
	SnapshotDigest string   `json:"snapshot_digest"`
}

ExecutionPolicy is the non-secret, deterministic execution surface an assignee must reproduce. SnapshotDigest also covers catalog instructions, so an external executor can fail closed if its local catalog has changed without putting those instructions in Aether task metadata or payload.

type ExecutionScopeAuthorizationRequest added in v0.0.2

type ExecutionScopeAuthorizationRequest struct {
	Parent    *workspacepkg.ExecutionScope
	Requested *workspacepkg.ExecutionScope
	Request   Request
	Reason    string
}

ExecutionScopeAuthorizationRequest is emitted only when a child attempts to select a different view, broaden write access, or resume a thread under a scope that is not a monotonic narrowing of its previous scope. Exact inheritance and read-only narrowing require no adapter.

type ExecutionScopeAuthorizer added in v0.0.2

type ExecutionScopeAuthorizer interface {
	AuthorizeSubagentExecutionScope(context.Context, ExecutionScopeAuthorizationRequest) error
}

ExecutionScopeAuthorizer is the enterprise/embedding seam for explicit view overrides. Nil is fail-closed: only exact inheritance and read-only narrowing are accepted.

type FileCatalog

type FileCatalog struct {
	// contains filtered or unexported fields
}

func NewFileCatalog

func NewFileCatalog(dir string) *FileCatalog

func (*FileCatalog) Get

func (c *FileCatalog) Get(ctx context.Context, typ AgentType) (Definition, error)

func (*FileCatalog) List

func (c *FileCatalog) List(ctx context.Context) ([]Definition, error)

type FileRegistry added in v0.0.2

type FileRegistry struct {
	// contains filtered or unexported fields
}

FileRegistry stores one parent-scoped registry per workspace. It is safe for concurrent use in one process; a state directory has one writing process.

func NewFileRegistry added in v0.0.2

func NewFileRegistry(stateDir string) (*FileRegistry, error)

func (*FileRegistry) ListSubagents added in v0.0.2

func (r *FileRegistry) ListSubagents(ctx context.Context, workspaceID, parentSessionID string) ([]spec.SessionSubagentRecord, error)

ListSubagents returns a deterministic deep copy for snapshot projection.

func (*FileRegistry) ObserveSubagent added in v0.0.2

func (r *FileRegistry) ObserveSubagent(ctx context.Context, event LifecycleEvent) error

ObserveSubagent atomically merges one lifecycle transition.

func (*FileRegistry) RecoverInterrupted added in v0.0.2

func (r *FileRegistry) RecoverInterrupted(ctx context.Context, at time.Time) error

RecoverInterrupted marks children left admitted/running by a prior process as interrupted. It validates the complete registry set before writing any file, so corrupt state fails startup without silently skipping another session.

type LifecycleEvent added in v0.0.2

type LifecycleEvent struct {
	WorkspaceID string
	Record      spec.SessionSubagentRecord
}

LifecycleEvent is an authoritative child-session registry update. The record uses the shared session protocol shape so local files, MemoryLayer adapters, Aether checkpoints, and remote clients project the same lifecycle fields.

type LifecycleObserver added in v0.0.2

type LifecycleObserver interface {
	ObserveSubagent(ctx context.Context, event LifecycleEvent) error
}

LifecycleObserver records subagent admission/running/terminal transitions. Runner execution treats observation as best-effort; recovery surfaces fail closed when a configured registry cannot be read or validated.

type OutputContract added in v0.0.2

type OutputContract struct {
	// contains filtered or unexported fields
}

OutputContract is a compiled, fail-closed subset of JSON Schema suitable for delegated result contracts. Unsupported assertion keywords are rejected at admission instead of being silently ignored.

func CompileOutputSchema added in v0.0.2

func CompileOutputSchema(raw json.RawMessage) (*OutputContract, error)

func (*OutputContract) Digest added in v0.0.2

func (c *OutputContract) Digest() string

func (*OutputContract) Raw added in v0.0.2

func (c *OutputContract) Raw() json.RawMessage

func (*OutputContract) Validate added in v0.0.2

func (c *OutputContract) Validate(raw json.RawMessage) []ValidationError

type PermissionMode

type PermissionMode string
const (
	PermissionModeInherit  PermissionMode = "inherit"
	PermissionModeAsk      PermissionMode = "ask"
	PermissionModeAllow    PermissionMode = "allow"
	PermissionModeReadOnly PermissionMode = "read_only"
)

type ProviderCatalog added in v0.0.2

type ProviderCatalog struct {
	// contains filtered or unexported fields
}

ProviderCatalog adapts a workspace provider to the existing subagent Catalog. A selected logical workspace may be bound to a different backend workspace; explicitly addressed other workspaces pass through unchanged.

func NewProviderCatalog added in v0.0.2

func NewProviderCatalog(provider WorkspaceDefinitionProvider, logicalWorkspace, backendWorkspaceID string) (*ProviderCatalog, error)

func (*ProviderCatalog) Get added in v0.0.2

func (*ProviderCatalog) GetWorkspace added in v0.0.2

func (c *ProviderCatalog) GetWorkspace(ctx context.Context, workspaceID string, typ AgentType) (Definition, error)

func (*ProviderCatalog) List added in v0.0.2

func (c *ProviderCatalog) List(ctx context.Context) ([]Definition, error)

func (*ProviderCatalog) ListWorkspace added in v0.0.2

func (c *ProviderCatalog) ListWorkspace(ctx context.Context, workspaceID string) ([]Definition, error)

type Ref

type Ref struct {
	// contains filtered or unexported fields
}

Ref is a late-bound Runner: the spawn tool can be registered (and thus surfaced to the model in the tool list) before the concrete runner exists, then wired via Set. RunSubagent returns ErrNoRunner until Set is called.

func (*Ref) RunSubagent

func (r *Ref) RunSubagent(ctx context.Context, req Request) (Result, error)

RunSubagent delegates to the installed runner.

func (*Ref) Set

func (r *Ref) Set(runner Runner)

Set installs the concrete runner.

func (*Ref) StartBackground

func (r *Ref) StartBackground(ctx context.Context, req Request) (string, error)

StartBackground forwards to the installed runner when it is a BackgroundRunner. It returns ErrNoRunner before Set is called and ErrBackgroundUnsupported when the installed runner lacks the detached-execution seam — so *Ref satisfies BackgroundRunner (a spawn tool holding the ref can attempt a background spawn) while still degrading cleanly on a backend that doesn't support it.

type Registry added in v0.0.2

type Registry interface {
	LifecycleObserver
	ListSubagents(ctx context.Context, workspaceID, parentSessionID string) ([]spec.SessionSubagentRecord, error)
	RecoverInterrupted(ctx context.Context, at time.Time) error
}

Registry is the durable lifecycle surface used by the runner and session snapshot projection.

type Request

type Request struct {
	Task   string
	Depth  int
	Parent protocol.MessageAddress
	// InvocationID identifies this spawn invocation independently from the child
	// thread. The reference tool supplies its stable tool-call ID so a durable
	// task backend can deduplicate an admission retry without collapsing later
	// follow-ups that resume the same child thread.
	InvocationID string
	GrantID      string
	SubjectType  string
	SubjectID    string
	// ExecutionScope pins the child to the parent's exact workspace view and
	// write ceiling. The spawn tool supplies it from trusted turn context; it is
	// never accepted as a model-authored absolute path or bearer grant.
	ExecutionScope *workspacepkg.ExecutionScope
	// CatalogRevision pins the immutable workspace catalog admitted by the
	// parent session so durable/external execution cannot silently use a newer
	// skill, MCP, or agent surface.
	CatalogRevision string
	// OutputSchema is an optional, admission-validated JSON Schema contract for
	// the child's final answer. The child receives it once in its bootstrap.
	OutputSchema json.RawMessage
	// Model optionally pins the sub-agent to a specific model (validated against
	// the registry by the runner; empty → the runner's normal per-turn selection).
	Model string
	// ResumeThreadID, when set, CONTINUES an existing child sub-agent thread
	// (used verbatim as the child thread id) instead of minting a new
	// "<parentThread>::sub::<seq>" thread. It is the handle returned as
	// Result.ThreadID from a prior spawn; empty → create a new child thread.
	ResumeThreadID string
	// ParentMessageID is the id of the spawning parent message, recorded on the
	// child thread's task message as MessageRef.ParentMessageID (the cross-thread
	// back-ref). Empty is acceptable (the back-ref still carries the parent
	// thread id).
	ParentMessageID string
	// Agent fields are populated when a file-backed catalog definition is used.
	// The OSS in-process runner applies Instructions, MaxTurns, AllowedTools,
	// DeniedTools, and Model. Skills, MCPServers, PermissionMode,
	// ExecPolicyHint, and Background are retained for catalog-compatible
	// backends until OSS has concrete runtime seams for them.
	AgentName      AgentName
	AgentType      AgentType
	Instructions   string
	MaxTurns       int
	AllowedTools   []string
	DeniedTools    []string
	Skills         []string
	MCPServers     []string
	PermissionMode PermissionMode
	ExecPolicyHint string
	Background     bool
}

Request is a sub-task delegation. Authority fields carry the parent turn's OBO grant (as primitives to avoid importing the tools package and creating a cycle) so the sub-agent acts on behalf of the same principal.

func ReconstructExecutionRequest added in v0.0.2

func ReconstructExecutionRequest(
	ctx context.Context,
	envelope ExecutionEnvelope,
	catalog Catalog,
	grantID, subjectType, subjectID string,
) (Request, error)

ReconstructExecutionRequest rebuilds the private Request policy an assigned executor must use. Named agent policies are loaded from the executor's local catalog and verified against the envelope digest; generic policies can be reconstructed only when they carried no private instructions. The delegated task text is intentionally left empty and must be resolved from Input by the execution runner after the durable task has been claimed.

func (Request) AllowsTool

func (r Request) AllowsTool(tool string) error

type Result

type Result struct {
	Text string
	// StructuredPayload is set when OutputSchema was supplied and the final JSON
	// passed host-side validation. StructuredDigest identifies those exact bytes.
	StructuredPayload json.RawMessage
	StructuredDigest  string
	// ThreadID is the child sub-agent thread's id — the re-addressable handle.
	// Pass it back as Request.ResumeThreadID to continue the same sub-agent.
	ThreadID string
	// Summary is a compact one-line digest of the answer (first line / first
	// ~200 chars), suitable for the parent to keep as a reference.
	Summary string
}

Result is the sub-agent's final answer.

type Runner

type Runner interface {
	RunSubagent(ctx context.Context, req Request) (Result, error)
}

Runner executes a sub-agent request.

type TaskAdmission added in v0.0.2

type TaskAdmission struct {
	WorkspaceID     string
	ParentSessionID string
	ChildSessionID  string
	ParentTaskID    string
	ParentMessageID string
	InvocationID    string
	Name            string
	Kind            string
	Model           string
	Depth           int
	Background      bool
	GrantID         string
	SubjectType     string
	SubjectID       string
	// Execution is the immutable, non-secret payload descriptor for an eventual
	// assignee. It references durable input/result/checkpoint state and records
	// claim/replay ownership without embedding prompt text or credentials.
	Execution ExecutionEnvelope
}

TaskAdmission is the non-secret identity and policy projection used to admit one subagent invocation to an optional durable task backend. Task is deliberately absent: prompts and OBO credentials do not belong in task metadata. InvocationID should be stable for a retried tool invocation (the spawn tool uses its tool-call ID), allowing a backend to deduplicate admission.

type TaskAwaiter added in v0.0.2

type TaskAwaiter interface {
	TaskBackend
	ExecutesExternally() bool
	Await(ctx context.Context, taskID string, observe func(TaskRecovery)) (TaskRecovery, error)
}

TaskAwaiter marks a backend whose admitted work is executed by another assignee. The parent must not call Start or Finish in this mode. Await reports authoritative state changes until a terminal state is reached; callbacks may repeat and must be cheap and concurrency-safe.

type TaskBackend added in v0.0.2

type TaskBackend interface {
	Admit(ctx context.Context, admission TaskAdmission) (taskID string, err error)
	Start(ctx context.Context, taskID string) error
	Finish(ctx context.Context, taskID string, outcome TaskOutcome, reason string) error
	Recover(ctx context.Context, taskID string) (TaskRecovery, error)
}

TaskBackend makes a durable task system the execution authority while the SubagentRegistry remains a parent-session snapshot projection. Implementations must make Admit idempotent for a non-empty InvocationID. Finish must return nil only when the requested terminal state is confirmed; after an ambiguous mutation it should query, not blindly repeat the mutation. Recover must return a terminal projection, terminating orphaned non-terminal work before returning TaskRecoveryInterrupted.

type TaskOutcome added in v0.0.2

type TaskOutcome string

TaskOutcome is the requested durable terminal state for one execution task.

const (
	TaskOutcomeCompleted TaskOutcome = "completed"
	TaskOutcomeFailed    TaskOutcome = "failed"
	TaskOutcomeCancelled TaskOutcome = "cancelled"
)

type TaskRecovery added in v0.0.2

type TaskRecovery string

TaskRecovery is the authoritative task state projected during owner restart. Interrupted means the backend found non-terminal work whose in-process execution was lost and durably terminated it; it must not be replayed.

const (
	TaskRecoveryAdmitted    TaskRecovery = "admitted"
	TaskRecoveryRunning     TaskRecovery = "running"
	TaskRecoveryCompleted   TaskRecovery = "completed"
	TaskRecoveryFailed      TaskRecovery = "failed"
	TaskRecoveryCancelled   TaskRecovery = "cancelled"
	TaskRecoveryInterrupted TaskRecovery = "interrupted"
)

type TaskRecoveryRegistry added in v0.0.2

type TaskRecoveryRegistry interface {
	Registry
	RecoverInterruptedWithTasks(ctx context.Context, at time.Time, tasks TaskBackend) error
}

TaskRecoveryRegistry is implemented by distributed registries that can reconcile incomplete projections with their execution authority during owner restart. Local registries deliberately retain process-owner interruption recovery and do not need this extension.

type ValidationError added in v0.0.2

type ValidationError struct {
	Path    string `json:"path"`
	Message string `json:"message"`
}

ValidationError is a deterministic, compact error returned to the child for its single correction attempt.

type WorkspaceCatalog added in v0.0.2

type WorkspaceCatalog interface {
	Catalog
	ListWorkspace(ctx context.Context, workspaceID string) ([]Definition, error)
	GetWorkspace(ctx context.Context, workspaceID string, typ AgentType) (Definition, error)
}

WorkspaceCatalog is the additive multi-workspace catalog capability. Legacy Catalog callers use the configured default; turn-aware callers address the resolved logical workspace explicitly.

type WorkspaceDefinitionProvider added in v0.0.2

type WorkspaceDefinitionProvider interface {
	LoadWorkspace(ctx context.Context, workspaceID string) ([]Definition, error)
}

WorkspaceDefinitionProvider loads the authoritative agent definitions for one logical workspace. Implementations must not silently fall back to another authority when a load fails.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL