Documentation
¶
Overview ¶
Package headless holds the platforms that run without an interactive terminal: platform/worker for one-shot batches and platform/timer for in-process schedules. Neither ever reads stdin, which is what makes them safe under systemd, cron, containers, and anywhere stdin is /dev/null.
Index ¶
- Constants
- func NewTimer(cfg TimerConfig) (agentkit.Platform, error)
- func NewWorker(cfg WorkerConfig, deps WorkerDeps) (agentkit.Platform, error)
- type TaskSpec
- type Timer
- func (t *Timer) PermissionCapability() permission.Capability
- func (t *Timer) PlatformID() string
- func (t *Timer) Receive(ctx context.Context) (agentkit.MessageEvent, error)
- func (t *Timer) Send(_ context.Context, event agentkit.OutboundEvent) error
- func (t *Timer) SetClockForTest(now func() time.Time, sleep func(context.Context, time.Duration) error)
- type TimerConfig
- type Worker
- func (w *Worker) PermissionCapability() permission.Capability
- func (w *Worker) PlatformID() string
- func (w *Worker) Receive(ctx context.Context) (agentkit.MessageEvent, error)
- func (w *Worker) Send(_ context.Context, event agentkit.OutboundEvent) error
- func (w *Worker) SetClockForTest(now func() time.Time, sleep func(context.Context, time.Duration) error)
- type WorkerConfig
- type WorkerDeps
Constants ¶
const ( OutputText = "text" OutputJSON = "json" )
Output modes.
const ( // SessionFresh gives every task or tick its own session. This is the default // because the alternative fails slowly: a periodic job pinned to one session // grows its context every tick until it hits the model's window. SessionFresh = "fresh" // SessionFixed reuses one session id so the agent remembers across runs. // Pair it with compaction, or the context grows without bound. SessionFixed = "fixed" )
Session id modes shared by worker and timer.
Variables ¶
This section is empty.
Functions ¶
func NewTimer ¶
func NewTimer(cfg TimerConfig) (agentkit.Platform, error)
NewTimer registers platform/timer: Fire the same prompt on a fixed interval.
Best practices:
- Ticks are anchored to the start time and missed ones are skipped, so a slow turn does not make the schedule drift.
- Use platform/worker with a cron expression when you need calendar times rather than an interval.
func NewWorker ¶
func NewWorker(cfg WorkerConfig, deps WorkerDeps) (agentkit.Platform, error)
NewWorker registers platform/worker: Headless task runner: one-shot prompts, shell scripts, or a resident cron daemon.
Best practices:
- Without any cron task the worker exits at EOF; with one it stays resident.
- A cron task needs the schedule dep, and a script task needs workspace and shell; both are checked at startup rather than silently skipped.
- Missed boundaries are skipped, not backfilled, so a restart does not replay a day of jobs.
Types ¶
type TaskSpec ¶
type TaskSpec struct {
Prompt string `json:"prompt"`
// Script is a workspace-relative path to a bash script executed directly.
Script string `json:"script,omitempty"`
// Cron, when set, turns this task into a scheduled job instead of a
// run-once-at-startup task.
Cron string `json:"cron,omitempty"`
// ID names the job in the registry and in logs. Defaults to task-<n>.
ID string `json:"id,omitempty"`
// Note is free-form context stored with the job.
Note string `json:"note,omitempty"`
}
TaskSpec is one worker task. In YAML it may be written either as a bare string (run once at startup) or as an object with a cron expression (run on that schedule, keeping the process resident).
Each task uses exactly one mode:
- prompt: send text to the agent as a turn
- script: run a workspace-relative bash script without an agent turn
func (*TaskSpec) UnmarshalJSON ¶
UnmarshalJSON accepts a bare string so `tasks: ["do a thing"]` keeps working alongside `tasks: [{prompt: "...", cron: "0 9 * * *"}]`.
type Timer ¶
type Timer struct {
// contains filtered or unexported fields
}
Timer turns the process into a daemon that wakes on a fixed interval. Ticks are anchored to the start time rather than to the end of the previous turn, so a slow turn does not make the schedule drift; missed boundaries are skipped rather than queued, because a backlog of stale ticks is never what a schedule meant.
func (*Timer) PermissionCapability ¶
func (t *Timer) PermissionCapability() permission.Capability
func (*Timer) PlatformID ¶ added in v0.1.1
type TimerConfig ¶
type TimerConfig struct {
// EverySeconds is the tick interval. Required.
EverySeconds int `json:"everySeconds"`
// Prompt is the task text sent on every tick. Required.
Prompt string `json:"prompt"`
// Immediate fires the first tick at startup instead of waiting a full
// interval. Defaults to true, so a restart does useful work right away.
Immediate *bool `json:"immediate"`
// MaxRuns bounds the number of ticks; 0 means run until shutdown.
MaxRuns int `json:"maxRuns"`
// SessionMode is fresh (default) or fixed.
SessionMode string `json:"sessionMode"`
// SessionID is the id used in fixed mode, and the prefix in fresh mode.
SessionID string `json:"sessionId"`
// Output is text (default) or json, one event object per line.
Output string `json:"output"`
// Stream echoes assistant deltas as they arrive.
Stream bool `json:"stream"`
}
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker runs a batch of tasks and, when a schedule registry is wired in, then stays resident firing cron jobs. It never reads stdin, so it is safe under cron, systemd, and CI.
func (*Worker) PermissionCapability ¶
func (w *Worker) PermissionCapability() permission.Capability
func (*Worker) PlatformID ¶ added in v0.1.1
type WorkerConfig ¶
type WorkerConfig struct {
// Tasks each run as one turn. Entries without a cron run once at startup, in
// order; entries with a cron are registered as scheduled jobs. Positional
// command-line arguments override this list.
Tasks []TaskSpec `json:"tasks"`
// Prompt is the single-task shorthand, used when Tasks is empty.
Prompt string `json:"prompt"`
// SessionMode is fresh (default) or fixed.
SessionMode string `json:"sessionMode"`
// SessionID is the id used in fixed mode, and the prefix in fresh mode.
SessionID string `json:"sessionId"`
// Output is text (default) or json, one event object per line.
Output string `json:"output"`
// Stream echoes assistant deltas as they arrive. Off by default: an
// unattended run wants the result, not the typing.
Stream bool `json:"stream"`
// PollSeconds is how often the cron loop re-reads the registry, which is what
// bounds the delay before a job the agent just scheduled is noticed.
// Defaults to 30.
PollSeconds int `json:"pollSeconds"`
}
type WorkerDeps ¶
type WorkerDeps struct {
// Schedule enables cron mode. Without it, cron-bearing tasks are a config
// error rather than a silently ignored setting.
Schedule schedule.Registry `json:"schedule,omitempty"`
// Workspace resolves script paths. Required when any task uses script.
Workspace workspace.Service `json:"workspace,omitempty"`
// Shell runs script tasks. Required when any task uses script.
Shell shell.Executor `json:"shell,omitempty"`
}