autonomy

package
v0.31.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package personal implements the domain-general durable state and runtime primitives for autonomous agents.

Index

Constants

View Source
const (
	BrowserExistingChrome = "existing_chrome"
	BrowserEphemeral      = "ephemeral"
)

Variables

This section is empty.

Functions

func AppendMemory

func AppendMemory(home, note string) error

AppendMemory adds one durable note. Append-only and deduplicated: a wake that re-learns something it already recorded must not grow the file without bound, since every line is replayed into the model on every future wake.

func CanonicalFilesystemGrant

func CanonicalFilesystemGrant(path string) (string, error)

func CanonicalPolicy

func CanonicalPolicy(p DelegationPolicy) ([]byte, string, error)

func CommitGenerated

func CommitGenerated(root, message string) error

func InitializeGeneratedWorkspace

func InitializeGeneratedWorkspace(home string) (string, error)

func InitializeHome

func InitializeHome(home string) error

func IsRestriction

func IsRestriction(parent, next DelegationPolicy) bool

func NextDue

func NextDue(kind, spec string, after time.Time) (time.Time, error)

NextDue resolves when a trigger should next fire.

The only kinds here are the ones an AGENT writes for itself from inside a run (schedule_wake: "come back in 45 minutes"), which are always a single future instant. Recurring cadence a HUMAN configures is not a trigger at all — it is an ordinary gateway schedule delivering to agent:<name>, parsed and validated once by gwconfig (see ValidateScheduleSpec/BuildSchedule).

That split is deliberate: this package used to carry its own interval/cron parsing, which meant two cron implementations in one binary and two places for scheduling rules to disagree. Adding kinds back here would rebuild the second scheduler — internal/guard's TestSingleCronParser fails if it happens.

func PathWithinGrant

func PathWithinGrant(path, root string) bool

PathWithinGrant reports whether path resolves (symlinks evaluated) to a location inside the canonical grant root. The requested path's symlinks are resolved before the containment check so a symlink inside a granted dir that points outside cannot escape the boundary.

func PrepareRunDirectory

func PrepareRunDirectory(home, runID string, e ExecutionEnvelope) (string, error)

func ReadMemory

func ReadMemory(home string) string

ReadMemory returns the agent's memory, or "" when it has none yet.

func RedactActionRequest

func RedactActionRequest(v json.RawMessage) json.RawMessage

func ResolveInteraction

func ResolveInteraction(s *Store, id, answer string) error

func RollbackGenerated

func RollbackGenerated(root, revision string) error

func SandboxAvailable

func SandboxAvailable() bool

func ValidateDelegation

func ValidateDelegation(parent DelegationPolicy, e ExecutionEnvelope) error

func ValidateExecutiveBudget

func ValidateExecutiveBudget(maxSeconds, maxTools, maxDelegation int) error

func WriteConfigMirror

func WriteConfigMirror(ctx context.Context, home string, s *Store) error

WriteConfigMirror regenerates config.yaml — ONE readable file in the agent's home holding the authority state that lives in the database: its policies (draft and approved) and its resource grants. This is what makes `ls ~/.memcode/agents/<name>/` show something a person can read, diff, and grep instead of only an opaque SQLite file, matching every other piece of memcode config (gateway.yaml, .mcp.json, MEMCODE.md, skills).

The agent's objective, autonomy, browser mode, and pause state are NOT here: they are ordinary configuration in gateway.yaml, which is already a readable file. Mirroring them too would mean two places to look and two chances to disagree.

This file is a MIRROR, not the source of truth — the DB stays authoritative for two reasons that are correctness, not habit:

  • Policy approval is a deliberate hash-gated ceremony (see ApprovePolicy): a autonomous agent runs unsupervised, so "the document a human actually reviewed" must be pinned by hash, not re-derived from whatever the file happens to say at wake time. Editing config.yaml's policy section and having it silently take effect would defeat that.
  • The action/trigger/interaction journal needs atomic claim/complete semantics under concurrent access (the gateway wake loop and an admin session can both touch the same agent) — a SQL transaction gives that almost for free; a flat file would need to reinvent it (see the atomicfile-write fix elsewhere in this package for how easily a plain file write loses that property). So the run journal stays out of this file entirely — read it with gw_journal.

Called after every mutation to policies/resources (gw_policy, gw_grant), best-effort: a mirror failure never blocks the underlying write, which has already succeeded.

Types

type Action

type Action struct {
	ID, ObjectiveID, SubgoalID, RunID, Kind, Target, ConsequenceClass, PolicyHash, Status, IdempotencyKey string
	// JobID links a delegate action to the detached job it spawned, so a later
	// wake can find the action to close out (see Store.ActionForJob).
	JobID                     string
	Request, Result, Evidence json.RawMessage
	CreatedAt, UpdatedAt      time.Time
}

type ActionIntent

type ActionIntent struct {
	ID, ObjectiveID, SubgoalID, RunID, Kind, Target string
	Consequence                                     ConsequenceClass
	PolicyHash                                      string
	Request                                         json.RawMessage
	IdempotencyKey                                  string
}

type ActionStatus

type ActionStatus string
const (
	ActionPlanned   ActionStatus = "planned"
	ActionReserved  ActionStatus = "reserved"
	ActionRunning   ActionStatus = "running"
	ActionSucceeded ActionStatus = "succeeded"
	ActionFailed    ActionStatus = "failed"
	ActionUncertain ActionStatus = "uncertain"
	ActionCancelled ActionStatus = "cancelled"
)

type ConsequenceClass

type ConsequenceClass string
const (
	Observe                ConsequenceClass = "observe"
	LocalMutation          ConsequenceClass = "local_mutation"
	ExternalEffect         ConsequenceClass = "external_effect"
	ExternalRepresentation ConsequenceClass = "external_representation"
	Financial              ConsequenceClass = "financial"
	LegalAttestation       ConsequenceClass = "legal_attestation"
	Destructive            ConsequenceClass = "destructive"
)

type DelegationPolicy

type DelegationPolicy struct {
	ObjectiveScope      string             `json:"objective_scope"`
	AllowedTools        []string           `json:"allowed_tools,omitempty"`
	FilesystemRoots     map[string]string  `json:"filesystem_roots,omitempty"`
	BrowserOrigins      []string           `json:"browser_origins,omitempty"`
	MCPTools            []string           `json:"mcp_tools,omitempty"`
	ConsequenceClasses  []ConsequenceClass `json:"consequence_classes,omitempty"`
	MaxActionsPerPeriod int                `json:"max_actions_per_period,omitempty"`
	MaxConcurrency      int                `json:"max_concurrency,omitempty"`
	MaxDelegationDepth  int                `json:"max_delegation_depth,omitempty"`
	MaxTokens           int                `json:"max_tokens,omitempty"`
	MaxSeconds          int                `json:"max_seconds,omitempty"`
	GeneratedCode       bool               `json:"generated_code,omitempty"`
	QuietHours          string             `json:"quiet_hours,omitempty"`
	ExpiresAt           *time.Time         `json:"expires_at,omitempty"`
	Revoked             bool               `json:"revoked,omitempty"`
}

func NarrowPolicy

func NarrowPolicy(parent, child DelegationPolicy) (DelegationPolicy, error)

func (DelegationPolicy) AllowsConsequence

func (p DelegationPolicy) AllowsConsequence(c ConsequenceClass, now time.Time) bool

type EffectivenessEvaluation

type EffectivenessEvaluation struct {
	Progress                               float64
	Success                                bool
	Elapsed                                time.Duration
	Cost                                   float64
	RepeatedSteps, Errors, UserCorrections int
	EnvironmentalInstability               bool
	CapabilityGap, Recommendation          string
}

type EvolutionChoice

type EvolutionChoice string
const (
	EvolutionContinue       EvolutionChoice = "continue"
	EvolutionChangeStrategy EvolutionChoice = "change_strategy"
	EvolutionReuse          EvolutionChoice = "reuse_artifact"
	EvolutionGenerate       EvolutionChoice = "generate_artifact"
	EvolutionImprove        EvolutionChoice = "improve_artifact"
	EvolutionRetire         EvolutionChoice = "retire_artifact"
	EvolutionEscalate       EvolutionChoice = "request_information_or_authority"
	EvolutionAbandon        EvolutionChoice = "abandon"
)

func ChooseEvolution

func ChooseEvolution(e EffectivenessEvaluation, hasCompatibleArtifact bool) EvolutionChoice

type ExecutionEnvelope

type ExecutionEnvelope struct {
	Task, ExpectedOutput, CompletionCondition string
	Context                                   json.RawMessage
	Toolsets                                  []string
	Resources                                 []string
	Consequences                              []ConsequenceClass
	Deadline                                  string
	Budgets                                   jobs.ExecutionBudgets
	ParentRunID, SubgoalID                    string
	AllowDelegation                           bool
	DelegationDepth                           int
	// BrowserSession selects the worker's browser backend when Toolsets
	// includes "browser": BrowserExistingChrome (the default for Personal
	// Agent delegation — the user's own already-running, already-logged-in
	// Chrome, reached through the gateway-owned broker) or BrowserEphemeral
	// (a fresh, logged-out profile — explicit opt-down only). See
	// docs/design/autonomous-agents.md "Browser broker trust boundary".
	BrowserSession string
}

type Executive

type Executive struct {
	Store   *Store
	Home    string
	AgentID string
	// Objective is the durable outcome this wake advances, read from the
	// agent's configuration (gwconfig.Agent.Objective) rather than the store —
	// a human edits it in one place and it hot-reloads. An empty Objective
	// blocks the run rather than inventing one.
	Objective string
	Runner    *llm.Runner
	Now       func() time.Time
	MaxSteps  int
	// DelegationDepth is this wake's own depth in a delegation chain — 0 for a
	// top-level RunOnce/ResumeSuspended wake. A worker spawned via delegate is
	// itself a plain `memcode run` job, not another Executive, so depth never
	// grows past 1 today; the field exists so ValidateDelegation's depth check
	// means something even before nested Personal-Agent delegation exists.
	DelegationDepth int
}

Executive is one bounded decision loop for an agent running unattended. Each RunOnce is a single bounded wake: read durable state, run one LLM turn with domain-neutral tools, journal consequential actions, then complete, schedule the next wake, or suspend for human input. It never holds an open loop.

func (*Executive) ResumeSuspended

func (e *Executive) ResumeSuspended(ctx context.Context, in Interaction, answer string) (RunOutcome, error)

ResumeSuspended continues a suspended run after its interaction is answered. It loads the saved transcript, appends the exact tool_result for the suspended tool_use_id, then re-enters the bounded loop so the model actually continues — no replay of completed actions, no fabricated user turn. It marks the continuation resolved ONLY after the resumed run finishes, so a failure leaves the interaction retryable.

func (*Executive) RunOnce

func (e *Executive) RunOnce(ctx context.Context) (RunOutcome, error)

RunOnce executes a single bounded wake for the agent's primary objective. It fails closed: no approved policy, inactive objective, or an expired/revoked policy all block consequential work before any LLM call is made.

type ExecutiveDecision

type ExecutiveDecision struct {
	Kind, SubgoalID, Reason string
	NextWake                *time.Time
}

func SelectNextAction

func SelectNextAction(state ExecutiveState, now time.Time) ExecutiveDecision

type ExecutiveState

type ExecutiveState struct {
	Objective           Objective
	Subgoals            []Subgoal
	PendingInteractions int
	RecentActions       []Action
	LastEvaluation      *EffectivenessEvaluation
}

type GeneratedIndex

type GeneratedIndex struct {
	Path, Hash, Purpose, SourceObjectiveID, SourceRunID, ParentRevision string
	BuildCommand, RunCommand, TestCommand                               []string
	Evaluations                                                         []EffectivenessEvaluation
	ActiveRevision                                                      string
}

type GeneratedItem

type GeneratedItem struct {
	ID, ObjectiveID, Path, Hash, Purpose, SourceRunID, ParentRevision, ActiveRevision string
	Invocation, Evaluations                                                           json.RawMessage
	LastUsedAt                                                                        *time.Time
	CreatedAt, UpdatedAt                                                              time.Time
}

type Interaction

type Interaction struct {
	ID, AgentID, ObjectiveID, RunID string
	Kind, Question, Context         string
	Answer                          *string
	Status                          string // pending | answered | cancelled
	ToolUseID                       string
	CreatedAt                       time.Time
	AnsweredAt                      *time.Time
}

Interaction is a durable human-in-the-loop request created by a suspending tool (ask_user). It lives in the agent's personal.db and is answered via `personal answer`. Resume is exact: the saved tool_use_id gets the answer.

func GetInteraction

func GetInteraction(s *Store, id string) (Interaction, bool, error)

func PendingInteractions

func PendingInteractions(s *Store, agentID string) ([]Interaction, error)

Package-level wrappers used by cmd (store passed explicitly).

type MissedRunPolicy

type MissedRunPolicy string
const (
	MissedSkip    MissedRunPolicy = "skip"
	MissedRunOnce MissedRunPolicy = "run_once"
	MissedCatchUp MissedRunPolicy = "catch_up"
)

type Notification

type Notification struct {
	ID, ObjectiveID, Kind, Status string
	Payload                       json.RawMessage
	CreatedAt, UpdatedAt          time.Time
}

type Objective

type Objective struct {
	ID, Description, SuccessCriteria, Status string
	Priority                                 int
	CreatedAt, UpdatedAt                     time.Time
	ReviewAt                                 *time.Time
}

type PacePolicy

type PacePolicy struct {
	BurstCap, PeriodLimit, Concurrency       int
	MinimumCooldown, BaseBackoff, MaxBackoff time.Duration
	QuietStart, QuietEnd                     int
}

type PaceState

type PaceState struct {
	PeriodStarted                time.Time
	Actions, ConsecutiveFailures int
	CooldownUntil                time.Time
	Suspended                    bool
	Warning                      string
}

func (PaceState) AfterFailure

func (s PaceState) AfterFailure(now time.Time, p PacePolicy, warning bool) PaceState

func (PaceState) AfterSuccess

func (s PaceState) AfterSuccess(now time.Time, p PacePolicy) PaceState

func (PaceState) Allow

func (s PaceState) Allow(now time.Time, p PacePolicy) bool

type Policy

type Policy struct {
	ID, ObjectiveID, Hash, Status string
	Version                       int
	Document                      json.RawMessage
	ApprovedAt                    *time.Time
	CreatedAt                     time.Time
}

type Resource

type Resource struct {
	ID, ObjectiveID, Type, Locator, AccessMode, AuthorizationSource, PolicyHash, Status string
	Constraints                                                                         json.RawMessage
	ExpiresAt                                                                           *time.Time
	CreatedAt, UpdatedAt                                                                time.Time
}

type ResourceGrantModel

type ResourceGrantModel struct {
	ID                                      string
	Type                                    ResourceType
	Locator, AccessMode                     string
	Constraints                             map[string]any
	AuthorizationSource, PolicyHash, Status string
	ExpiresAt                               *time.Time
}

func (ResourceGrantModel) Active

func (g ResourceGrantModel) Active(now time.Time) bool

type ResourceType

type ResourceType string
const (
	ResourceFilesystem       ResourceType = "filesystem"
	ResourceBrowser          ResourceType = "browser"
	ResourceMCP              ResourceType = "mcp"
	ResourceCommand          ResourceType = "command"
	ResourceRepository       ResourceType = "repository"
	ResourceCloud            ResourceType = "cloud"
	ResourceDocument         ResourceType = "document"
	ResourceChannel          ResourceType = "channel"
	ResourceGeneratedProcess ResourceType = "generated_process"
)

type Run

type Run struct {
	ID, ObjectiveID, SubgoalID, ParentRunID, SessionID string
	Envelope, Outcome, Evidence                        json.RawMessage
	Status                                             string
	CreatedAt, UpdatedAt                               time.Time
}

type RunOutcome

type RunOutcome struct {
	RunID         string     `json:"run_id"`
	Status        string     `json:"status"`
	Report        string     `json:"report"`
	NextWakeAt    *time.Time `json:"next_wake_at,omitempty"`
	InteractionID string     `json:"interaction_id,omitempty"`
}

type RunResult

type RunResult struct {
	Stdout, Stderr string
	ExitCode       int
	ChangedFiles   []string
}

func RunGenerated

func RunGenerated(ctx context.Context, s RunSpec) (RunResult, error)

type RunSpec

type RunSpec struct {
	Executable             string
	Args                   []string
	Inputs                 map[string][]byte
	AllowedExecutables     []string
	Timeout                time.Duration
	MaxOutputBytes         int
	Environment            map[string]string
	RequireHardenedSandbox bool
}

type Store

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

func Open

func Open(ctx context.Context, home string) (*Store, error)

func (*Store) ActionForJob

func (s *Store) ActionForJob(ctx context.Context, jobID string) (string, error)

ActionForJob returns the id of the action that spawned jobID, or "" when there is none.

func (*Store) ApprovePolicy

func (s *Store) ApprovePolicy(ctx context.Context, hash string) error

func (*Store) ApprovedPolicy

func (s *Store) ApprovedPolicy(ctx context.Context, objectiveID string) (Policy, bool, error)

func (*Store) CancelInteraction

func (s *Store) CancelInteraction(ctx context.Context, id string) error

func (*Store) CancelPendingNotifications

func (s *Store) CancelPendingNotifications(ctx context.Context) error

func (*Store) ClaimDueTrigger

func (s *Store) ClaimDueTrigger(ctx context.Context, id string, now time.Time) (Trigger, bool, error)

func (*Store) Close

func (s *Store) Close() error

func (*Store) CompleteAction

func (s *Store) CompleteAction(ctx context.Context, id string, status ActionStatus, result, evidence json.RawMessage) error

func (*Store) CreateObjective

func (s *Store) CreateObjective(ctx context.Context, o Objective) error

func (*Store) CreateRun

func (s *Store) CreateRun(ctx context.Context, r Run) error

func (*Store) CreateTrigger

func (s *Store) CreateTrigger(ctx context.Context, t Trigger) error

func (*Store) DB

func (s *Store) DB() *sql.DB

DB exposes the underlying handle for store-internal submodules (same package); external callers use Store methods only.

func (*Store) DeleteObjective

func (s *Store) DeleteObjective(ctx context.Context, id string) error

func (*Store) DueTriggers

func (s *Store) DueTriggers(ctx context.Context, now time.Time) ([]Trigger, error)

DueTriggers returns only enabled triggers whose next_due_at has passed, filtered in SQL rather than pulling every trigger row (including completed ones) and filtering in Go on every poll.

func (*Store) GetInteraction

func (s *Store) GetInteraction(ctx context.Context, id string) (Interaction, bool, error)

func (*Store) GetObjective

func (s *Store) GetObjective(ctx context.Context, id string) (Objective, bool, error)

func (*Store) InsertInteraction

func (s *Store) InsertInteraction(ctx context.Context, in Interaction) error

func (*Store) InsertNotification

func (s *Store) InsertNotification(ctx context.Context, n Notification) error

func (*Store) InsertPolicy

func (s *Store) InsertPolicy(ctx context.Context, p Policy) error

func (*Store) InsertResource

func (s *Store) InsertResource(ctx context.Context, r Resource) error

func (*Store) LinkActionJob

func (s *Store) LinkActionJob(ctx context.Context, actionID, jobID string) error

LinkActionJob records which detached job an action spawned, so a later wake can find its way back from a job id to the action it must close out.

func (*Store) ListActions

func (s *Store) ListActions(ctx context.Context, objectiveID string, limit int) ([]Action, error)

func (*Store) ListObjectives

func (s *Store) ListObjectives(ctx context.Context) ([]Objective, error)

func (*Store) ListPolicies

func (s *Store) ListPolicies(ctx context.Context, objectiveID string) ([]Policy, error)

func (*Store) ListResources

func (s *Store) ListResources(ctx context.Context, objectiveID string) ([]Resource, error)

func (*Store) ListRuns

func (s *Store) ListRuns(ctx context.Context, objectiveID string, limit int) ([]Run, error)

func (*Store) ListSubgoals

func (s *Store) ListSubgoals(ctx context.Context, objectiveID string) ([]Subgoal, error)

func (*Store) ListTriggers

func (s *Store) ListTriggers(ctx context.Context) ([]Trigger, error)

func (*Store) MarkActionRunning

func (s *Store) MarkActionRunning(ctx context.Context, id string) error

func (*Store) NextPolicyVersion

func (s *Store) NextPolicyVersion(ctx context.Context, objectiveID string) (int, error)

func (*Store) PendingInteractions

func (s *Store) PendingInteractions(ctx context.Context, agentID string) ([]Interaction, error)

func (*Store) RecoverableRuns

func (s *Store) RecoverableRuns(ctx context.Context) ([]Run, error)

func (*Store) ReserveAction

func (s *Store) ReserveAction(ctx context.Context, a ActionIntent) (Action, bool, error)

func (*Store) ResolveInteraction

func (s *Store) ResolveInteraction(ctx context.Context, id, answer string) error

ResolveInteraction atomically marks a pending interaction answered. Returns an error if it was already resolved (prevents double-resume of a suspended run).

func (*Store) ResolveUncertainAction

func (s *Store) ResolveUncertainAction(ctx context.Context, id string, status ActionStatus) error

func (*Store) RevokeResources

func (s *Store) RevokeResources(ctx context.Context, objectiveID string) error

func (*Store) SetObjectiveStatus

func (s *Store) SetObjectiveStatus(ctx context.Context, id, status string) error

func (*Store) SetObjectiveText

func (s *Store) SetObjectiveText(ctx context.Context, id, description string) error

SetObjectiveText updates an objective's description (the user-authored goal).

func (*Store) SetResourceStatus

func (s *Store) SetResourceStatus(ctx context.Context, id, status string) error

func (*Store) SetSubgoalStatus

func (s *Store) SetSubgoalStatus(ctx context.Context, id, status string) error

func (*Store) StatusSummary

func (s *Store) StatusSummary(ctx context.Context) (map[string]int, error)

func (*Store) UpdateRunStatus

func (s *Store) UpdateRunStatus(ctx context.Context, id, status string, outcome json.RawMessage) error

func (*Store) UpsertSubgoal

func (s *Store) UpsertSubgoal(ctx context.Context, g Subgoal) error

type Subgoal

type Subgoal struct {
	ID, ObjectiveID, ParentID, Description, Status, Rationale string
	Priority                                                  int
	Dependencies                                              json.RawMessage
	CreatedAt, UpdatedAt                                      time.Time
}

type Trigger

type Trigger struct {
	ID, ObjectiveID, Kind, Spec, MissedRunPolicy, Status string
	NextDueAt, LastFiredAt                               *time.Time
	CreatedAt, UpdatedAt                                 time.Time
}

Jump to

Keyboard shortcuts

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