dsl

package
v0.9.3 Latest Latest
Warning

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

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

Documentation

Overview

Package dsl provides a YAML-based domain-specific language for defining AI agent teams and workflows without writing Go code.

DSL Overview

The DSL uses YAML files (typically named *.vega.yaml) to define:

  • Agents: AI assistants with specific roles and capabilities
  • Workflows: Multi-step processes that coordinate agents
  • Tools: Custom tool definitions with various implementations
  • Settings: Global configuration like rate limits and budgets

Basic Example

A simple .vega.yaml file:

name: My Team

agents:
  assistant:
    model: claude-sonnet-4-6
    system: You are a helpful assistant.

workflows:
  greet:
    inputs:
      name:
        type: string
        required: true
    steps:
      - assistant:
          send: "Hello, {{name}}!"
          save: greeting
    output: "{{greeting}}"

Using the DSL

Parse and execute a DSL file:

parser := dsl.NewParser()
doc, err := parser.ParseFile("team.vega.yaml")
if err != nil {
    log.Fatal(err)
}

interp, err := dsl.NewInterpreter(doc)
if err != nil {
    log.Fatal(err)
}
defer interp.Shutdown()

result, err := interp.Execute(ctx, "greet", map[string]any{
    "name": "World",
})

Expression Syntax

The DSL supports {{expression}} interpolation:

{{variable}}           - Simple variable reference
{{step1.field}}        - Nested field access
{{value | upper}}      - Filter/transform
{{name | default:anon}} - Filter with argument

Available filters: upper, lower, trim, default, lines, words, truncate, join

Control Flow

The DSL supports various control structures:

# Conditionals
- if: "{{approved}}"
  then:
    - agent: ...
  else:
    - agent: ...

# Loops
- for: item in items
  steps:
    - agent:
        send: "Process {{item}}"

# Repeat until condition
- repeat:
    max: 5
    until: "'done' in result"
    steps:
      - agent: ...

# Parallel execution
- parallel:
    - agent1: ...
    - agent2: ...

See the examples/ directory in the repository for complete examples.

Package dsl provides the Vega DSL parser and interpreter.

Index

Constants

View Source
const (
	StepStatusRunning   = "running"
	StepStatusCompleted = "completed"
	StepStatusFailed    = "failed"
)

Step lifecycle statuses reported to the step observer.

View Source
const DefaultMaxConcurrentDispatches = 4

DefaultMaxConcurrentDispatches is the default cap on simultaneous background dispatch goroutines.

View Source
const DefaultMaxDelegationDepth = 8

DefaultMaxDelegationDepth bounds how many agent-to-agent delegation hops a single originating request may chain. Without a bound, an A→B→A dispatch ping-pong (a confused or prompt-injected agent re-delegating) burns full LLM turns forever. Override with VEGA_MAX_DELEGATION_DEPTH.

View Source
const DispatchTriageThreshold = 3

DispatchTriageThreshold is the auto-age cutoff used by list_inbox. After this many reads without an orchestrator-driven resolution, the item gets a synthetic "auto-aged" resolution and disappears from the pending queue. Tuned conservatively (3) so a temporary stall during the orchestrator's reasoning doesn't drop a real action item.

View Source
const HeraAgentName = "hera"

HeraAgentName is the default canonical name for the agent-builder meta-agent.

View Source
const IrisAgentName = "iris"

IrisAgentName is the default canonical name for the orchestrator meta-agent.

View Source
const MaxReactiveDepth = 2

MaxReactiveDepth is the maximum depth for reactive channel notifications to prevent infinite loops.

Variables

View Source
var DefaultGradientPalette = [][]string{
	{"#A78BFA", "#7C3AED"},
	{"#0EA5E9", "#22D3EE"},
	{"#EF4444", "#DC2626"},
	{"#F59E0B", "#D97706"},
	{"#10B981", "#059669"},
	{"#EC4899", "#DB2777"},
	{"#3B82F6", "#2563EB"},
	{"#14B8A6", "#0D9488"},
	{"#F97316", "#EA580C"},
	{"#8B5CF6", "#6D28D9"},
	{"#84CC16", "#65A30D"},
	{"#06B6D4", "#0891B2"},
}

DefaultGradientPalette is the curated set of 2-stop CSS color arrays new agents pick from when none was supplied. Each pair reads well as a small avatar disc against both light and dark backgrounds.

View Source
var DefaultIconPalette = []string{
	"Sparkles",
	"Bot",
	"Cpu",
	"Briefcase",
	"Compass",
	"Flame",
	"Gem",
	"Heart",
	"Rocket",
	"Star",
	"Wand2",
	"Zap",
}

DefaultIconPalette is the curated set of Lucide icon names new agents pick from when none was supplied. Names are kept generic so the icon rarely contradicts the agent's role.

Functions

func BuildTeamPrompt

func BuildTeamPrompt(system string, team []string, agentDescriptions map[string]string, blackboardEnabled bool) string

BuildTeamPrompt appends team delegation instructions to a system prompt. agentDescriptions is optional — if a member has a description it is shown. When blackboardEnabled is true, instructions about bb_read/bb_write/bb_list tools are appended.

func ChannelReactiveDepthFromContext added in v0.3.0

func ChannelReactiveDepthFromContext(ctx context.Context) int

ChannelReactiveDepthFromContext returns the current reactive depth from ctx.

func ChannelToolNames added in v0.8.14

func ChannelToolNames() []string

ChannelToolNames is the canonical list of channel tools every agent gets in its tool surface. The spawn filter pulls this into the always-available bucket so a per-agent Tools allow-list never gates channel participation: every agent can post updates, read the full backlog, and list its channels.

Gating these behind a per-agent allow-list left custom personas mute in channels — they'd be added to a channel's team but couldn't post, so they improvised (saving files, asking the human to relay). Channel participation is first-class for all, mirroring WikiMemoryToolNames for the shared wiki.

func ContainsExpression

func ContainsExpression(s string) bool

ContainsExpression checks if a string contains expressions.

func ContextWithChannelReactiveDepth added in v0.3.0

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

ContextWithChannelReactiveDepth returns a new context with the given reactive depth.

func ContextWithWorkflowRunID added in v0.8.0

func ContextWithWorkflowRunID(ctx context.Context, runID string) context.Context

ContextWithWorkflowRunID attaches the run ID a server allocated for this workflow execution, so step events can be correlated with the persisted workflow_runs row.

func DefaultAgentSystem added in v0.6.0

func DefaultAgentSystem(displayName, name string) string

DefaultAgentSystem returns a minimal "you are <name>." system prompt used when the caller didn't provide one. Without an identity the LLM can drift into the orchestrator's persona because the tool surface is its only signal (issue #48). Prefer display_name for the identity if set.

func DefaultNonMetaToolNames added in v0.6.0

func DefaultNonMetaToolNames(schema []llm.ToolSchema) []string

DefaultNonMetaToolNames returns every tool in schema except those that belong exclusively to Hera or Iris. Used by every agent-creation path (HTTP handler, Hera's create_agent tool, restore-on-boot) when the caller didn't specify a tool list — empty Tools means spawnAgent gives the agent everything, which leaks meta-tools to composed agents.

func DefaultVisualIdentity added in v0.6.0

func DefaultVisualIdentity(seed string) (icon string, gradient []string)

DefaultVisualIdentity picks an (icon, gradient) pair for a newly-created agent when the caller didn't supply one. The choice is deterministic in seed (typically the agent name) so the same agent always gets the same identity across restarts and caller paths. An empty seed picks the first entries — stable and harmless.

Used by every agent-creation path (HTTP handleCreateAgent, Hera's DSL create_agent tool) to avoid blank icon/color placeholders on the frontend (refs govega#60).

func ExtractExpressions

func ExtractExpressions(s string) []string

ExtractExpressions finds all {{...}} expressions in a string.

func FormatDelegationContext

func FormatDelegationContext(dc *DelegationContext, message string) string

FormatDelegationContext wraps the original message with caller context as XML.

func InjectHera added in v0.4.0

func InjectHera(interp *Interpreter, cfg HeraConfig, cb *HeraCallbacks, extraTools ...string) error

InjectHera adds the agent-builder to the interpreter using cfg. Pass DefaultHeraConfig() for the standard Hera persona, or override fields to customize identity. extraTools are additional tool names (e.g. scheduler tools) to include in the agent's tool list — they must already be registered on the interpreter.

func InjectIris added in v0.4.0

func InjectIris(interp *Interpreter, cfg IrisConfig, channelBackend ChannelBackend, extraTools ...string) error

InjectIris adds the orchestrator agent to the interpreter using cfg. Pass DefaultIrisConfig() to use the bundled Iris persona, or override fields to customize the agent's identity. extraTools are additional tool names (e.g. memory tools) to include in the agent's tool list — they must already be registered on the interpreter.

func IsHeraTool added in v0.4.0

func IsHeraTool(name string) bool

IsHeraTool reports whether a tool name is one of Hera's meta-tools.

func IsIrisTool added in v0.4.0

func IsIrisTool(name string) bool

IsIrisTool reports whether a tool name is one of Iris's tools.

func NewBlackboardListTool

func NewBlackboardListTool(getGroup GroupResolver) tools.ToolDef

NewBlackboardListTool creates a tool that lists all keys on the team blackboard.

func NewBlackboardReadTool

func NewBlackboardReadTool(getGroup GroupResolver) tools.ToolDef

NewBlackboardReadTool creates a tool that reads a key from the team blackboard.

func NewBlackboardWriteTool

func NewBlackboardWriteTool(getGroup GroupResolver) tools.ToolDef

NewBlackboardWriteTool creates a tool that writes a key/value pair to the team blackboard.

func NewDelegateTool

func NewDelegateTool(sendFn SendFunc, teamResolver TeamResolver) tools.ToolDef

NewDelegateTool returns a tools.ToolDef for the delegate tool. sendFn is called when the tool is invoked to relay a message to another agent. teamResolver is called at invocation time to determine which agents the caller can delegate to; if it returns nil/empty, any agent name is accepted.

func NewDelegateToolWithOpts added in v0.4.0

func NewDelegateToolWithOpts(opts DelegateToolOpts) tools.ToolDef

NewDelegateToolWithOpts returns a delegate tool with full configuration. When a ChannelPeerResolver is provided, agents that share a channel with the caller are also allowed as delegation targets — not just explicit team members.

func RegisterChannelTools added in v0.3.0

func RegisterChannelTools(interp *Interpreter, backend ChannelBackend, onPost ChannelPostCallback, onReactive ChannelReactiveCallback, onLifecycle ChannelLifecycleCallback)

RegisterChannelTools registers channel tools on the interpreter.

func RegisterDelegateTool

func RegisterDelegateTool(t *tools.Tools, sendFn SendFunc, teamResolver TeamResolver) bool

RegisterDelegateTool registers the delegate tool on the given Tools instance if it is not already registered. teamResolver is called at invocation time to determine which agents the caller can delegate to. Returns true if registration happened.

func RegisterDelegateToolWithOpts added in v0.4.0

func RegisterDelegateToolWithOpts(t *tools.Tools, opts DelegateToolOpts) bool

RegisterDelegateToolWithOpts registers the delegate tool with full options. Returns true if registration happened.

func RegisterHeraTools added in v0.4.0

func RegisterHeraTools(interp *Interpreter, cfg HeraConfig, cb *HeraCallbacks)

RegisterHeraTools registers the builder's meta-tools on the interpreter's global tool collection. cfg.Name is used to protect Hera from rename/delete via her own tools. The callbacks are optional — when nil, no persistence hooks fire.

func RegisterInboxTools added in v0.3.0

func RegisterInboxTools(interp *Interpreter, backend InboxBackend)

RegisterInboxTools registers the inbox tools on the interpreter.

ask_orchestrator is the canonical name; ask_iris is registered as a backward-compat alias for any yaml-defined or composed agent that references the old name. Both call the same backing function.

list_inbox and resolve_inbox are added to the orchestrator's tool list by the caller (Iris/Apex).

func RegisterIrisTools added in v0.4.0

func RegisterIrisTools(interp *Interpreter, cfg IrisConfig, channelBackend ...ChannelBackend)

RegisterIrisTools registers the orchestrator's tools on the interpreter's global tool collection. list_agents is registered only if not already present (Hera registers it when she's injected). channelBackend is optional — when provided, enables the check_status tool.

func RegisterSchedulerTools

func RegisterSchedulerTools(interp *Interpreter, backend SchedulerBackend)

RegisterSchedulerTools registers the four schedule-management tools on Hera's interpreter. Call this after InjectHera so the tools exist before Hera's tool list is finalised.

func RegisterTaskTools added in v0.6.0

func RegisterTaskTools(interp *Interpreter, backend TaskBackend)

RegisterTaskTools registers the seven kanban-interaction tools on the interpreter. The caller (server.go) decides which to add to which agent's tool list — typically all seven for the orchestrator (Iris) and a subset for worker agents.

func TruncatePreview added in v0.8.14

func TruncatePreview(s string, max int, suffix string) string

TruncatePreview shortens s to at most max runes for use in a preview that is later rendered as (or embedded inside) Markdown, then appends suffix if any truncation occurred. It fixes the byte-slice anti-pattern that scattered the codebase (content[:150], preview[:300], …): a raw byte slice can split a multibyte UTF-8 rune in half and cut a Markdown token mid-span, so an unterminated **bold** or `code` span renders as literal asterisks/backticks downstream.

It does three things a byte slice does not:

  • truncates on a rune boundary, never emitting invalid UTF-8;
  • backs off to the last word boundary near the limit for a clean cut;
  • closes a still-open inline code or bold span before the suffix, so the preview always renders as balanced Markdown.

Balancing is deliberately limited to the two tokens that caused real breakage (inline `code` and **bold**); single-* / _ italics and links are left as-is. Inside an open code span all other tokens are literal, so bold is only balanced when the code span is already balanced.

Types

type Agent

type Agent struct {
	Name        string `yaml:"name"`
	DisplayName string `yaml:"display_name"`
	Title       string `yaml:"title"`
	// Description is a short paragraph of body text describing the agent's
	// purpose, surfaced on agent cards and detail pages. Distinct from
	// `system` (which is the LLM-facing prompt) — intended for users.
	Description string `yaml:"description,omitempty" json:"description,omitempty"`
	Avatar      string `yaml:"avatar"`
	// Icon is a Lucide icon name (frontend uses lucide-react). Lets each
	// agent render with a distinctive glyph instead of an identical robot.
	Icon string `yaml:"icon,omitempty" json:"icon,omitempty"`
	// AvatarGradient is a 2-stop CSS color array (e.g. ["#EF4444", "#DC2626"])
	// used as the background gradient behind the icon/avatar.
	AvatarGradient []string `yaml:"avatar_gradient,omitempty" json:"avatar_gradient,omitempty"`
	Extends        string   `yaml:"extends"`
	Model          string   `yaml:"model"`
	FallbackModel  string   `yaml:"fallback_model"`
	// Models maps step-type tags (e.g. "classify", "code", "summarize") to
	// model IDs. Lookups that miss this map fall back to Model. Unset keys
	// are filled at validate time from Settings.DefaultModels.
	Models         map[string]string  `yaml:"models,omitempty"`
	System         string             `yaml:"system"`
	Temperature    *float64           `yaml:"temperature"`
	MaxTokens      int                `yaml:"max_tokens"`
	Effort         string             `yaml:"effort"` // "low" | "medium" | "high" | "xhigh" | "max"
	Budget         string             `yaml:"budget"` // e.g., "$0.50"
	Tools          []string           `yaml:"tools"`
	Knowledge      []string           `yaml:"knowledge"`
	Team           []string           `yaml:"team"`
	Supervision    *SupervisionDef    `yaml:"supervision"`
	Retry          *RetryDef          `yaml:"retry"`
	RateLimit      *RateLimitDef      `yaml:"rate_limit"`
	CircuitBreaker *CircuitBreakerDef `yaml:"circuit_breaker"`
	Skills         *SkillsDef         `yaml:"skills"`
	Delegation     *DelegationDef     `yaml:"delegation"`
	Memory         *MemoryDef         `yaml:"memory"`
	// Triggers declare the events this agent reacts to (reactive cognition).
	// See docs/reactive-agents-design.md §4.2.
	Triggers []TriggerDef `yaml:"triggers,omitempty" json:"triggers,omitempty"`

	// Norm is the name of a top-level `norms:` entry whose guidance is
	// composed into this agent's system prompt at spawn time. Empty
	// means no norm is applied. The parser validates that the name
	// resolves to a defined norm.
	Norm string `yaml:"norm,omitempty" json:"norm,omitempty"`

	// IsMeta marks an agent as a built-in meta-agent (e.g. orchestrator,
	// builder). Meta-agents are filtered out of "team" / "channel member"
	// listings and protected from runtime mutation. Set by Inject*-style
	// constructors; not parsed from YAML.
	IsMeta bool `yaml:"-" json:"-"`
}

Agent represents an agent definition in the DSL.

func HeraAgent added in v0.4.0

func HeraAgent(cfg HeraConfig) *Agent

HeraAgent returns the DSL agent definition for the agent-builder using cfg. Pass DefaultHeraConfig() for the standard Hera persona.

func IrisAgent added in v0.4.0

func IrisAgent(cfg IrisConfig) *Agent

IrisAgent returns the DSL agent definition for the orchestrator using cfg. Pass DefaultIrisConfig() (or a struct populated by IrisConfig.applyDefaults) for the standard Iris persona.

type AgentTemplate added in v0.3.0

type AgentTemplate struct {
	Version        string   `json:"version" yaml:"version"`
	Name           string   `json:"name" yaml:"name"`
	DisplayName    string   `json:"display_name,omitempty" yaml:"display_name,omitempty"`
	Title          string   `json:"title,omitempty" yaml:"title,omitempty"`
	Description    string   `json:"description,omitempty" yaml:"description,omitempty"`
	Avatar         string   `json:"avatar,omitempty" yaml:"avatar,omitempty"`
	Icon           string   `json:"icon,omitempty" yaml:"icon,omitempty"`
	AvatarGradient []string `json:"avatar_gradient,omitempty" yaml:"avatar_gradient,omitempty"`
	Model          string   `json:"model" yaml:"model"`
	System         string   `json:"system" yaml:"system"`
	Tools          []string `json:"tools,omitempty" yaml:"tools,omitempty"`
	Team           []string `json:"team,omitempty" yaml:"team,omitempty"`
	ExportedBy     string   `json:"exported_by,omitempty" yaml:"exported_by,omitempty"`
	ExportedAt     string   `json:"exported_at,omitempty" yaml:"exported_at,omitempty"`
}

AgentTemplate is a portable agent definition for export/import across instances.

type ChannelBackend added in v0.3.0

type ChannelBackend interface {
	CreateChannel(id, name, description, createdBy string, team []string, mode string) error
	GetChannelByName(name string) (*ChannelInfo, error)
	ListAllChannels() ([]ChannelInfo, error)
	ListChannelsForAgent(agent string) ([]ChannelInfo, error)
	FindChannelForAgents(agent1, agent2 string) (channelID string, channelName string, err error)
	InsertChannelMessage(channelID, agent, role, content string, threadID *int64, metadata, sender string, activities []vega.ToolActivity) (int64, error)
	RecentChannelMessages(channelID string, limit int) ([]ChannelMessage, error)
}

ChannelBackend is the interface for channel operations. Defined here so dsl/ does not import serve/.

type ChannelDef added in v0.4.0

type ChannelDef struct {
	Description string   `yaml:"description"`
	Team        []string `yaml:"team"`
	Mode        string   `yaml:"mode"` // "" (default) or "social"
}

ChannelDef defines a channel in the DSL.

type ChannelInfo added in v0.3.0

type ChannelInfo struct {
	ID   string
	Name string
	Team []string
}

ChannelInfo holds minimal channel data returned to dsl tools.

type ChannelLifecycleCallback added in v0.6.0

type ChannelLifecycleCallback func(id, name, description, createdBy string, team []string, mode string)

ChannelLifecycleCallback is called after an agent successfully creates a channel via the create_channel tool, so the server can publish a broker event (channel.created) for connected SSE clients. The HTTP channel handlers publish their own broker events directly — this hook covers the agent-driven tool path that bypasses HTTP.

type ChannelMessage added in v0.3.0

type ChannelMessage struct {
	Agent   string
	Sender  string
	Content string
}

ChannelMessage holds a single message returned by RecentChannelMessages.

type ChannelPeerResolver added in v0.4.0

type ChannelPeerResolver func(callerAgent, targetAgent string) bool

ChannelPeerResolver checks whether two agents share a channel. Returns true if callerAgent and targetAgent are members of any common channel.

type ChannelPostCallback added in v0.3.0

type ChannelPostCallback func(channelName, agent, content string, msgID int64, threadID *int64)

ChannelPostCallback is called after an agent posts to a channel, so the server can publish SSE events to connected clients.

type ChannelReactiveCallback added in v0.3.0

type ChannelReactiveCallback func(channelName string, team []string, poster string, message string, depth int, triggerMsgID int64)

ChannelReactiveCallback is called after a post_to_channel so that other team members can be notified and optionally respond. triggerMsgID is the message that triggered the reaction, so agents can reply in-thread.

type CircuitBreakerDef added in v0.5.0

type CircuitBreakerDef struct {
	Threshold   int    `yaml:"threshold"`     // failures before opening
	ResetAfter  string `yaml:"reset_after"`   // e.g., "30s", "1m"
	HalfOpenMax int    `yaml:"half_open_max"` // probes allowed in half-open
}

CircuitBreakerDef is DSL circuit breaker configuration.

type Company added in v0.3.0

type Company struct {
	ID          string           `yaml:"id" json:"id"`
	Name        string           `yaml:"name" json:"name"`
	Description string           `yaml:"description,omitempty" json:"description,omitempty"`
	Location    string           `yaml:"location,omitempty" json:"location,omitempty"`
	LogoURL     string           `yaml:"logo_url,omitempty" json:"logo_url,omitempty"`
	AccentColor string           `yaml:"accent_color,omitempty" json:"accent_color,omitempty"`
	Siblings    []CompanySibling `yaml:"siblings,omitempty" json:"siblings,omitempty"`
}

Company represents the company identity for a Vega instance.

type CompanySibling added in v0.3.0

type CompanySibling struct {
	Name string `yaml:"name" json:"name"`
	URL  string `yaml:"url" json:"url"`
	Icon string `yaml:"icon,omitempty" json:"icon,omitempty"`
}

CompanySibling represents a sibling Vega instance for company switching.

type DelegateToolOpts added in v0.4.0

type DelegateToolOpts struct {
	SendFn              SendFunc
	TeamResolver        TeamResolver
	ChannelPeerResolver ChannelPeerResolver // optional — allows delegation to channel peers
}

DelegateToolOpts configures the delegate tool.

type DelegationContext

type DelegationContext struct {
	CallerAgent string
	Messages    []llm.Message
}

DelegationContext holds extracted caller context for enriched delegation.

func ExtractCallerContext

func ExtractCallerContext(callerProc *vega.Process, config *DelegationDef) *DelegationContext

ExtractCallerContext reads the last N messages from the caller process, optionally filtering by role. Returns nil if no messages match.

type DelegationDef

type DelegationDef struct {
	ContextWindow int      `yaml:"context_window"` // number of recent messages to forward
	IncludeRoles  []string `yaml:"include_roles"`  // filter by role (user, assistant, system)
	Blackboard    bool     `yaml:"blackboard"`     // enable shared blackboard for team
}

DelegationDef configures context-aware delegation for an agent.

type DelegationObserver added in v0.3.0

type DelegationObserver func(ctx context.Context, fromAgent, toAgent, message, response string)

DelegationObserver is called after each agent-to-agent delegation completes. It receives the caller agent name, target agent name, the delegation message, and the response. Implementations should not block.

type Document

type Document struct {
	Name        string                 `yaml:"name"`
	Description string                 `yaml:"description"`
	Agents      map[string]*Agent      `yaml:"agents"`
	Channels    map[string]*ChannelDef `yaml:"channels"`
	Workflows   map[string]*Workflow   `yaml:"workflows"`
	Tools       map[string]*ToolDef    `yaml:"tools"`
	// Norms are named guidance blocks that can be appended to an agent's
	// system prompt at runtime. Use the interpreter's Norm() accessor to
	// look one up by name; the host application decides which norm (if
	// any) applies to a given session via the ExtraSystemProvider hook.
	Norms    map[string]*Norm `yaml:"norms,omitempty"`
	Settings *Settings        `yaml:"settings"`
	Company  *Company         `yaml:"company,omitempty"`
}

Document represents a parsed .vega.yaml file.

type ExecutionContext

type ExecutionContext struct {
	// Inputs are the workflow input values
	Inputs map[string]any

	// Variables holds step outputs and set values
	Variables map[string]any

	// CurrentStep is the index of the executing step
	CurrentStep int

	// LoopState for loop iterations
	LoopState *LoopState

	// StartTime is when execution began
	StartTime time.Time

	// Timeout for the entire workflow
	Timeout time.Duration
}

ExecutionContext holds state during workflow execution.

type GlobalSkillsDef

type GlobalSkillsDef struct {
	Directories []string `yaml:"directories"`
}

GlobalSkillsDef configures global skill settings.

type GroupResolver

type GroupResolver func(ctx context.Context) *vega.ProcessGroup

GroupResolver returns the team ProcessGroup for the calling process.

type HeraCallbacks added in v0.4.0

type HeraCallbacks struct {
	OnAgentCreated func(agent *Agent) error
	OnAgentDeleted func(name string)
	// OnProvisioning fires at multiple phases during create_agent so the
	// server can stream SSE events to the FE (refs govega#56). The
	// callback runs synchronously inside the tool body — keep it cheap.
	OnProvisioning func(event ProvisioningEvent)
	ChannelBackend ChannelBackend // optional — auto-creates channels for team leads
}

HeraCallbacks receives notifications when Hera creates or deletes agents. Serve mode uses this to persist composed agents to the database.

type HeraConfig added in v0.5.0

type HeraConfig struct {
	Name                    string // lowercase slug (default: "hera")
	DisplayName             string // capitalized name (default: "Hera")
	Title                   string // role label shown on agent cards (default: "Agent Builder")
	OrchestratorName        string // companion orchestrator's slug (default: "iris")
	OrchestratorDisplayName string // companion orchestrator's display name (default: "Iris")
	ProductName             string // product/universe name (default: "Vega")
	SystemPrompt            string // optional prompt override
	Model                   string
	FallbackModel           string
	// Models is an optional per-step-type routing table — see
	// Agent.ModelFor. When nil, applyDefaults seeds it with Hera's
	// recommended defaults (classify on Haiku for first-turn intent).
	Models map[string]string
}

HeraConfig customizes the agent-builder's identity. Apps embedding govega can override the slug/display name and the orchestrator companion's name. SystemPrompt is optional — when empty the bundled template is used.

func DefaultHeraConfig added in v0.5.0

func DefaultHeraConfig() HeraConfig

DefaultHeraConfig returns the bundled Hera persona with original names.

type InboxBackend added in v0.3.0

type InboxBackend interface {
	InsertInboxItem(fromAgent, subject, body, priority string) (int64, error)
	InsertResolvedInboxItem(fromAgent, subject, body, resolution string) (int64, error)
	ListInboxItems(status string, limit int) ([]InboxItem, error)
	ResolveInboxItem(id int64, resolution string) error
	DeleteInboxItem(id int64) error
	TriageInboxItems(ids []int64, threshold int) ([]int64, error)
}

InboxBackend is the interface that the store implements for inbox operations. Defined here so dsl/ does not import serve/.

type InboxItem added in v0.3.0

type InboxItem struct {
	ID            int64      `json:"id"`
	FromAgent     string     `json:"from_agent"`
	Subject       string     `json:"subject"`
	Body          string     `json:"body,omitempty"`
	Priority      string     `json:"priority"`
	Status        string     `json:"status"`
	Resolution    string     `json:"resolution,omitempty"`
	CreatedAt     time.Time  `json:"created_at"`
	ResolvedAt    *time.Time `json:"resolved_at,omitempty"`
	TriageCount   int        `json:"triage_count"`
	LastTriagedAt *time.Time `json:"last_triaged_at,omitempty"`
}

InboxItem represents a message posted to Iris's inbox by another agent.

type Input

type Input struct {
	Type        string   `yaml:"type"`
	Description string   `yaml:"description"`
	Required    bool     `yaml:"required"`
	Default     any      `yaml:"default"`
	Enum        []string `yaml:"enum"`
	Min         *float64 `yaml:"min"`
	Max         *float64 `yaml:"max"`
}

Input defines a workflow input parameter.

type Interpreter

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

Interpreter executes DSL workflows.

func NewInterpreter

func NewInterpreter(doc *Document, opts ...InterpreterOption) (*Interpreter, error)

NewInterpreter creates a new interpreter for a document.

func (*Interpreter) AddAgent

func (i *Interpreter) AddAgent(name string, def *Agent) error

AddAgent adds and spawns a new agent at runtime.

func (*Interpreter) Agents

func (i *Interpreter) Agents() map[string]*vega.Process

Agents returns a copy of the active agent processes map.

func (*Interpreter) DispatchToAgent added in v0.3.0

func (i *Interpreter) DispatchToAgent(ctx context.Context, agentName string, message string) (string, error)

DispatchToAgent is a non-blocking variant of SendToAgent. It validates the agent exists, then spawns a goroutine that calls SendToAgent. On completion (or error), it posts an inbox item so the orchestrator knows the work finished. Returns immediately with a confirmation message.

The caller's agent name (read from the parent ctx's process) is captured before the goroutine detaches and forwarded to onDispatchComplete so downstream layers (e.g. serve.Server) can route the result back to the originating conversation — not just to the base orchestrator.

func (*Interpreter) Document

func (i *Interpreter) Document() *Document

Document returns the parsed DSL document.

func (*Interpreter) EnsureAgent

func (i *Interpreter) EnsureAgent(name string) (*vega.Process, error)

EnsureAgent ensures the named agent process is spawned and returns it. If the process already exists it is returned immediately; otherwise the agent is lazily spawned from its definition.

func (*Interpreter) EnsureSessionAgent added in v0.8.16

func (i *Interpreter) EnsureSessionAgent(name, base string) error

EnsureSessionAgent makes sure a per-session instance of a base agent is spawned under the composite name (e.g. "ea:session123"). It shallow-copies the base definition so the session inherits its persona, tools, and model, but gets its own process and — because chat history is keyed by agent name — its own conversation thread. Idempotent: a no-op if the session agent is already registered. This lets a guest-facing agent hold an isolated conversation per session without a first-class session dimension in the store.

func (*Interpreter) Execute

func (i *Interpreter) Execute(ctx context.Context, name string, inputs map[string]any) (any, error)

Execute runs a workflow by name (alias for RunWorkflow).

func (*Interpreter) HasAgent added in v0.7.13

func (i *Interpreter) HasAgent(name string) bool

HasAgent reports whether an agent with this name is defined (whether or not it is currently spawned). Useful for routing decisions where a caller wants to validate a target name without forcing a spawn.

func (*Interpreter) IsMetaAgent added in v0.7.17

func (i *Interpreter) IsMetaAgent(name string) bool

IsMetaAgent reports whether the named agent is a system (meta) agent such as Hera or Iris. Used to gate LLM-invokable agent-management tools so a prompt-injected agent can't have them delete or rewrite system agents.

func (*Interpreter) Norm added in v0.6.0

func (i *Interpreter) Norm(name string) (*Norm, bool)

Norm returns the named norm definition from the loaded document. The boolean is false when no norm is registered under that name.

func (*Interpreter) Orchestrator

func (i *Interpreter) Orchestrator() *vega.Orchestrator

Orchestrator returns the underlying orchestrator.

func (*Interpreter) PublishEvent added in v0.7.13

func (i *Interpreter) PublishEvent(e events.Event)

PublishEvent emits an event onto the spine if a publisher is wired.

func (*Interpreter) ReactiveTriggers added in v0.7.13

func (i *Interpreter) ReactiveTriggers() map[string][]reactive.Trigger

ReactiveTriggers returns each agent's reactive triggers, keyed by the name that SendToAgent accepts. Satisfies reactive.TriggerRegistry, so the router reads triggers off agent definitions — the single source of truth (D1).

It reads *definitions* (i.doc.Agents), not spawned processes, on purpose: under lazy-spawn a purely-reactive agent may never have been messaged, and idle agents get evicted — but their triggers must still be discoverable so the agent can wake. SendToAgent spawns the agent on the wake itself.

func (*Interpreter) RemoveAgent

func (i *Interpreter) RemoveAgent(name string) error

RemoveAgent stops and removes an agent at runtime.

func (*Interpreter) RemoveComposedAgents added in v0.4.0

func (i *Interpreter) RemoveComposedAgents()

RemoveComposedAgents kills and removes all agents that were NOT defined in the original YAML file and are not meta-agents (iris, hera). This restores the interpreter to its YAML-defined state after a reset.

func (*Interpreter) ResetAgent

func (i *Interpreter) ResetAgent(name string) error

ResetAgent kills the agent process and removes it from the active map, but preserves the agent definition so it respawns fresh on next use.

func (*Interpreter) RunWorkflow

func (i *Interpreter) RunWorkflow(ctx context.Context, name string, inputs map[string]any) (any, error)

RunWorkflow executes a workflow by name.

func (*Interpreter) SendToAgent

func (i *Interpreter) SendToAgent(ctx context.Context, agentName string, message string) (string, error)

SendToAgent sends a message to a specific agent and returns the response. If the calling context carries an event sink (from a streaming parent), SendToAgent uses streaming and forwards nested tool_start/tool_end events to the parent sink so the UI can display sub-agent activity in real time.

When invoked from inside another agent's tool loop (i.e. as a delegated subagent call), the target runs in a fresh, ephemeral process spawned from its definition. Each delegation thus starts with an empty message buffer, preventing accumulated cross-conversation history from one caller showing up in unrelated calls from another. Direct user-driven chat sessions continue to use the long-lived process so multi-turn conversations behave as users expect. Set VEGA_EPHEMERAL_DELEGATION=false to opt back into the legacy shared-process behavior.

func (*Interpreter) SetChannelBackend added in v0.3.0

func (i *Interpreter) SetChannelBackend(b ChannelBackend, onPost func(channelName, agent, content string, msgID int64, threadID *int64))

SetChannelBackend sets the channel backend used by DispatchToAgent to post completion summaries to the agent's team channel.

func (*Interpreter) SetDelegationCtxDecorator added in v0.5.0

func (i *Interpreter) SetDelegationCtxDecorator(fn func(ctx context.Context, agentName string) context.Context)

SetDelegationCtxDecorator sets a callback that rewrites the context before each delegation. The serve layer uses this to scope memory context to the delegated agent so each agent's remember/recall tools use their own namespace.

func (*Interpreter) SetDelegationObserver added in v0.3.0

func (i *Interpreter) SetDelegationObserver(fn DelegationObserver)

SetDelegationObserver registers a callback that fires after each delegation.

func (*Interpreter) SetDispatchCompleteCallback added in v0.4.0

func (i *Interpreter) SetDispatchCompleteCallback(fn func(ctx context.Context, agentName, callerName, message, response string, err error))

SetDispatchCompleteCallback registers a callback that fires when a dispatched agent finishes. Args:

  • agentName: the agent that just completed (e.g. "riley")
  • callerName: the agent that called send_to_agent (e.g. "apex"), or empty when the dispatch isn't attributable to an agent (e.g. a scheduler-triggered turn)
  • message: the original task message sent to the agent
  • response: the agent's final response
  • err: any error from the dispatch

The serve layer uses these to (a) route the orchestrator's response back to the originating conversation and (b) persist the dispatched exchange to the agent's private chat history so the user can watch their work in /chat/<agent>.

func (*Interpreter) SetDispatchEventCallback added in v0.5.1

func (i *Interpreter) SetDispatchEventCallback(fn func(agentName string, ev vega.ChatEvent))

SetDispatchEventCallback registers a callback that fires for every ChatEvent (text delta, tool start/end, etc.) emitted during a dispatched agent's run. The serve layer uses this to broadcast live progress to anyone watching the dispatched agent's private chat.

func (*Interpreter) SetDispatchStartCallback added in v0.4.0

func (i *Interpreter) SetDispatchStartCallback(fn func(agentName string))

SetDispatchStartCallback registers a callback that fires when a dispatched agent begins working. The serve layer uses this to show a busy indicator.

func (*Interpreter) SetEventPublisher added in v0.7.13

func (i *Interpreter) SetEventPublisher(fn func(e events.Event))

SetEventPublisher wires the interpreter (and the tools it hosts) to the reactive event spine. serve sets this to the bus's Publish so, e.g., the remember tool can emit memory.wrote. Nil is a safe no-op.

func (*Interpreter) SetInboxBackend added in v0.3.0

func (i *Interpreter) SetInboxBackend(b InboxBackend)

SetInboxBackend sets the inbox backend used by DispatchToAgent for posting completion notifications.

func (*Interpreter) SetMemoryInjector added in v0.3.0

func (i *Interpreter) SetMemoryInjector(fn func(proc *vega.Process, agentName string))

SetMemoryInjector sets a callback that injects memory into an agent process before sending messages. This gives agents access to their stored memories during delegated tasks, not just during direct chat.

func (*Interpreter) SetServerBaseURL added in v0.4.0

func (i *Interpreter) SetServerBaseURL(url string)

SetServerBaseURL sets the base URL of the Vega server so agents can construct workspace URLs for deliverables.

func (*Interpreter) SetStepObserver added in v0.8.0

func (i *Interpreter) SetStepObserver(fn StepObserver)

SetStepObserver installs the step lifecycle observer.

func (*Interpreter) Shutdown

func (i *Interpreter) Shutdown()

Shutdown stops all agents and disconnects MCP servers.

func (*Interpreter) SkillsLoader

func (i *Interpreter) SkillsLoader() *skills.Loader

SkillsLoader returns the global skills loader, or nil if none is configured.

func (*Interpreter) StartIdleEviction added in v0.5.1

func (i *Interpreter) StartIdleEviction(ctx context.Context, idleTTL, sweepInterval time.Duration)

StartIdleEviction launches a background sweep that periodically removes agent processes from the registry whose last_active_at is older than idleTTL. Composed agents (those NOT in yamlAgents) and non-meta processes are eligible; meta-agents (orchestrator, builder) and YAML-defined agents stay resident. Evicted processes are gracefully stopped — a subsequent EnsureAgent call respawns them on demand from the document definition.

Cancel via the supplied context. Safe to call once during server startup; subsequent calls would spawn duplicate sweeps.

func (*Interpreter) StreamToAgent

func (i *Interpreter) StreamToAgent(ctx context.Context, agentName string, message string) (*vega.ChatStream, error)

StreamToAgent sends a message to a specific agent and returns a ChatStream with structured events for real-time streaming and tool call visibility.

func (*Interpreter) StreamToAgentWithImages added in v0.8.12

func (i *Interpreter) StreamToAgentWithImages(ctx context.Context, agentName, message string, images []llm.ContentBlock) (*vega.ChatStream, error)

StreamToAgentWithImages is StreamToAgent for a multimodal user turn: text plus image content blocks the (vision-capable) agent reads this turn.

func (*Interpreter) Tools

func (i *Interpreter) Tools() *tools.Tools

Tools returns the tool registry.

type InterpreterOption

type InterpreterOption func(*Interpreter)

InterpreterOption configures the interpreter.

func WithLLM added in v0.7.13

func WithLLM(backend llm.LLM) InterpreterOption

WithLLM overrides the LLM backend used by every spawned agent. Without it, the interpreter builds a default backend from the environment. Primarily for tests that need a deterministic fake, but also usable by embedders.

func WithLazySpawn

func WithLazySpawn() InterpreterOption

WithLazySpawn defers agent process creation until first use. Useful for serve mode where agents are only needed when workflows run.

type IrisConfig added in v0.5.0

type IrisConfig struct {
	Name               string // lowercase slug for routing/registration (default: "iris")
	DisplayName        string // capitalized name shown in UI/prompt (default: "Iris")
	Title              string // role label shown on agent cards (default: "Orchestrator")
	BuilderName        string // companion builder's slug (default: "hera")
	BuilderDisplayName string // companion builder's display name (default: "Hera")
	ProductName        string // product/universe name (default: "Vega")
	SystemPrompt       string // optional prompt override; if empty the bundled template is used
	Model              string // optional model override
	FallbackModel      string // optional fallback model override
	// Models is an optional per-step-type routing table — see
	// Agent.ModelFor. When nil, applyDefaults seeds it with Iris's
	// recommended defaults (classify on Haiku for routing decisions).
	Models map[string]string
}

IrisConfig customizes the orchestrator agent's identity. Apps embedding govega can override the agent's lowercase slug, capitalized display name, builder companion name, and product name. The default Iris persona uses the bundled system prompt; override SystemPrompt to bring your own.

func DefaultIrisConfig added in v0.5.0

func DefaultIrisConfig() IrisConfig

DefaultIrisConfig returns the bundled Iris persona with original names.

type LoggingDef

type LoggingDef struct {
	Level string `yaml:"level"` // debug, info, warn, error
	File  string `yaml:"file"`
}

LoggingDef is DSL logging configuration.

type LoopState

type LoopState struct {
	Index int
	Count int
	Item  any
	First bool
	Last  bool
}

LoopState tracks loop iteration state.

type MCPDef

type MCPDef struct {
	Servers []MCPServerDef `yaml:"servers"`
}

MCPDef configures MCP servers.

type MCPServerDef

type MCPServerDef struct {
	Name         string            `yaml:"name"`
	Transport    string            `yaml:"transport"`
	Command      string            `yaml:"command"`
	Args         []string          `yaml:"args"`
	Env          map[string]string `yaml:"env"`
	URL          string            `yaml:"url"`
	Headers      map[string]string `yaml:"headers"`
	Timeout      string            `yaml:"timeout"`
	FromRegistry bool              `yaml:"-"` // resolved from registry, not serialized
}

MCPServerDef configures an individual MCP server.

type MemoryDef added in v0.5.1

type MemoryDef struct {
	// Reflect enables a small post-turn reflection inference that asks the
	// model what is worth remembering and writes typed memories on the
	// agent's behalf. Default false. The global VEGA_REFLECTION env var
	// can override (false=kill switch, true=on for every agent).
	Reflect bool `yaml:"reflect"`
}

MemoryDef configures per-agent memory behavior.

type Norm added in v0.6.0

type Norm struct {
	Description string `yaml:"description,omitempty" json:"description,omitempty"`
	System      string `yaml:"system" json:"system"`
}

Norm is a named writing/style guidance block defined in YAML. The `system` field is the text appended to an agent's system prompt when the norm is active for a session. `description` is human-facing copy for selection UIs.

type Parser

type Parser struct {
	// BaseDir for resolving relative paths
	BaseDir string
}

Parser parses .vega.yaml files.

func NewParser

func NewParser() *Parser

NewParser creates a new parser.

func (*Parser) Parse

func (p *Parser) Parse(data []byte) (*Document, error)

Parse parses YAML content into a Document.

func (*Parser) ParseFile

func (p *Parser) ParseFile(path string) (*Document, error)

ParseFile parses a .vega.yaml file.

type ProvisioningEvent added in v0.6.0

type ProvisioningEvent struct {
	Phase    ProvisioningPhase
	Name     string
	Snapshot *Agent // non-nil from field_set onward
	Err      error  // set only when Phase == failed
}

ProvisioningEvent is one tick in the create_agent lifecycle.

type ProvisioningPhase added in v0.6.0

type ProvisioningPhase string

ProvisioningPhase tags where in the create_agent flow an event was emitted.

const (
	// ProvisioningPhaseStarted fires as soon as create_agent has a valid name.
	// Earliest signal the FE can use to render a placeholder card.
	ProvisioningPhaseStarted ProvisioningPhase = "started"
	// ProvisioningPhaseFieldSet fires after the agent definition is fully
	// built (display_name, title, avatar, icon, gradient, tools, team)
	// but before AddAgent runs. The snapshot carries every user-visible
	// field so the FE can paint a complete card.
	ProvisioningPhaseFieldSet ProvisioningPhase = "field_set"
	// ProvisioningPhaseReady fires after AddAgent succeeds — the agent's
	// process is spawned and ready to accept work. Persistence may not
	// have happened yet; the OnAgentCreated callback fires for that.
	ProvisioningPhaseReady ProvisioningPhase = "ready"
	// ProvisioningPhaseFailed fires when any step in create_agent returns
	// an error. Lets the FE clear the placeholder rather than leave it
	// hanging.
	ProvisioningPhaseFailed ProvisioningPhase = "failed"
)

type REPL added in v0.5.0

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

REPL provides an interactive terminal chat for a Vega interpreter.

func NewREPL added in v0.5.0

func NewREPL(interp *Interpreter, opts ...REPLOption) *REPL

NewREPL creates a new REPL for the given interpreter.

func (*REPL) Run added in v0.5.0

func (r *REPL) Run()

Run starts the interactive REPL loop.

type REPLOption added in v0.5.0

type REPLOption func(*REPL)

REPLOption configures a REPL.

func WithREPLInput added in v0.5.0

func WithREPLInput(r io.Reader) REPLOption

WithREPLInput sets the input reader (default: os.Stdin).

func WithREPLOutput added in v0.5.0

func WithREPLOutput(w io.Writer) REPLOption

WithREPLOutput sets the output writer (default: os.Stdout).

func WithREPLPrompt added in v0.5.0

func WithREPLPrompt(name string) REPLOption

WithREPLPrompt sets the app name shown in the prompt (default: "vega").

func WithREPLTimeout added in v0.5.0

func WithREPLTimeout(d time.Duration) REPLOption

WithREPLTimeout sets the timeout for agent messages (default: 5 minutes).

type RateLimitDef

type RateLimitDef struct {
	RequestsPerMinute int `yaml:"requests_per_minute"`
	TokensPerMinute   int `yaml:"tokens_per_minute"`
}

RateLimitDef is DSL rate limit configuration.

type Repeat

type Repeat struct {
	Steps []Step `yaml:"steps"`
	Until string `yaml:"until"`
	Max   int    `yaml:"max"`
}

Repeat defines a repeat-until loop.

type ReplyTarget added in v0.5.1

type ReplyTarget interface {
	Reply(ctx context.Context, content string) error
}

ReplyTarget is the channel-of-origin abstraction. Entrypoints (Telegram bot, web chat handler, future SMS/Slack/etc. adapters) construct one and the serve layer registers it keyed by the agent name they're routing messages to (e.g. "apex" for the web app, "apex:123456789" for a per-user Telegram clone).

When async work dispatched from that agent completes, the dispatch- complete callback uses the registered target to push the orchestrator's response back to the originating channel — Telegram users get a bot message on their chat, web users see an SSE-driven chat refresh.

A nil ReplyTarget means "the inbox + chat history are the only sinks"; the work still completes, but no proactive push happens.

type RetryDef

type RetryDef struct {
	MaxAttempts int    `yaml:"max_attempts"`
	Backoff     string `yaml:"backoff"` // linear, exponential, constant
}

RetryDef is DSL retry configuration.

type ScheduledJob

type ScheduledJob struct {
	Name      string `json:"name"`
	Cron      string `json:"cron"`    // standard 5-field cron expression
	AgentName string `json:"agent"`   // agent to message on schedule
	Message   string `json:"message"` // message to send
	Enabled   bool   `json:"enabled"`
	// InMemoryOnly skips the persist callback on AddJob. Used for jobs that
	// are derived from server config (e.g. the orchestrator heartbeat) and
	// must be re-created from config each boot — persisting them strands
	// stale rows after a rename (govega#101).
	InMemoryOnly bool `json:"-"`
}

ScheduledJob describes a recurring agent trigger.

type SchedulerBackend

type SchedulerBackend interface {
	AddJob(job ScheduledJob) error
	RemoveJob(name string) error
	ListJobs() []ScheduledJob
}

SchedulerBackend is the interface that serve.Scheduler implements. Defined here so dsl/ does not import serve/.

type SendFunc

type SendFunc func(ctx context.Context, agent string, message string) (string, error)

SendFunc sends a message to a named agent and returns the response.

type Settings

type Settings struct {
	DefaultModel string `yaml:"default_model"`
	// DefaultModels is a document-wide step-type → model fallback table.
	// Each agent inherits any keys it hasn't set in its own Models map.
	DefaultModels      map[string]string `yaml:"default_models,omitempty"`
	DefaultTemperature *float64          `yaml:"default_temperature"`
	Sandbox            string            `yaml:"sandbox"`
	Budget             string            `yaml:"budget"`
	Supervision        *SupervisionDef   `yaml:"supervision"`
	RateLimit          *RateLimitDef     `yaml:"rate_limit"`
	Logging            *LoggingDef       `yaml:"logging"`
	Tracing            *TracingDef       `yaml:"tracing"`
	MCP                *MCPDef           `yaml:"mcp"`
	Skills             *GlobalSkillsDef  `yaml:"skills"`
}

Settings are global configuration.

type SkillsDef

type SkillsDef struct {
	Directories []string `yaml:"directories"`
	Include     []string `yaml:"include"`
	Exclude     []string `yaml:"exclude"`
	MaxActive   int      `yaml:"max_active"`
}

SkillsDef configures skills for an agent.

type Step

type Step struct {
	// Agent step fields
	Agent           string `yaml:"-"` // Extracted from key
	Action          string `yaml:"-"` // Extracted from key
	Send            string `yaml:"send"`
	Save            string `yaml:"save"`
	Timeout         string `yaml:"timeout"`
	Budget          string `yaml:"budget"`
	Retry           int    `yaml:"retry"`
	If              string `yaml:"if"`
	ContinueOnError bool   `yaml:"continue_on_error"`
	Format          string `yaml:"format"` // json, yaml, etc.

	// Control flow fields
	Condition string `yaml:"-"` // For if steps
	Then      []Step `yaml:"then"`
	Else      []Step `yaml:"else"`

	// Loop fields
	ForEach string  `yaml:"for"`   // "item in items"
	Steps   []Step  `yaml:"steps"` // for-each body
	Repeat  *Repeat `yaml:"repeat"`

	// Parallel fields
	Parallel []Step `yaml:"parallel"`

	// Sub-workflow fields
	Workflow string         `yaml:"workflow"`
	With     map[string]any `yaml:"with"`

	// Special fields
	Set    map[string]any `yaml:"set"`
	Return string         `yaml:"return"`
	Try    []Step         `yaml:"try"`
	Catch  []Step         `yaml:"catch"`

	// Raw for flexible parsing
	Raw map[string]any `yaml:"-"`
}

Step is a workflow step (can be various types). This uses a flexible structure to handle the natural language format.

type StepEvent added in v0.8.0

type StepEvent struct {
	// Index is the step's position in the workflow's top-level steps.
	Index int `json:"index"`
	// Name labels the step: the agent name for agent steps, otherwise
	// the step kind (set, for, return, ...).
	Name string `json:"name"`
	// Status is one of the StepStatus* constants.
	Status string `json:"status"`
	// Error carries the failure message for StepStatusFailed.
	Error string `json:"error,omitempty"`
	// At is when the transition happened.
	At time.Time `json:"at"`
}

StepEvent describes one lifecycle transition of a workflow step. The server persists these as run checkpoints (govega#114 Phase 5: workflow durability) so an operator can see where an interrupted run died.

type StepObserver added in v0.8.0

type StepObserver func(runID, workflow string, ev StepEvent)

StepObserver receives step lifecycle events for a workflow run. runID is the value attached via ContextWithWorkflowRunID (empty when the caller didn't attach one). Called synchronously from the workflow goroutine — keep it fast.

type SupervisionDef

type SupervisionDef struct {
	Strategy    string `yaml:"strategy"` // restart, stop, escalate
	MaxRestarts int    `yaml:"max_restarts"`
	Window      string `yaml:"window"` // e.g., "10m"
}

SupervisionDef is DSL supervision configuration.

type Task added in v0.6.0

type Task struct {
	ID          string     `json:"id"`
	Title       string     `json:"title"`
	Description string     `json:"description"`
	Status      string     `json:"status"`
	Priority    string     `json:"priority"`
	Assignee    string     `json:"assignee"`
	Tags        string     `json:"tags"`
	CreatedBy   string     `json:"created_by"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	DueAt       *time.Time `json:"due_at,omitempty"`
}

Task is the dsl-side mirror of serve.Task — the same shape, but defined here so dsl/ does not import serve/. The serve-side adapter converts between the two.

type TaskBackend added in v0.6.0

type TaskBackend interface {
	InsertTask(t Task) error
	GetTask(id string) (*Task, error)
	ListMyTasks(assignee string, status []string, limit int) ([]Task, error)
	ListUnassignedTasks(limit int) ([]Task, error)
	UpdateTaskStatus(id, status string) error
	AssignTask(id, assignee string) error
	ClaimTask(id, assignee string) error // sets assignee=caller, status=doing
	AddTaskComment(taskID, author, content string) (int64, error)
	LinkTaskProcess(taskID, processID string) error
}

TaskBackend is implemented by the store. Defined here so dsl/ stays free of a serve/ import.

type TeamResolver added in v0.3.0

type TeamResolver func(ctx context.Context) []string

TeamResolver returns the team members for the calling agent from context. It is called at invocation time so that team changes are picked up dynamically.

type ToolDef

type ToolDef struct {
	Name           string      `yaml:"name"`
	Description    string      `yaml:"description"`
	Params         []ToolParam `yaml:"params"`
	Implementation *ToolImpl   `yaml:"implementation"`
	Include        []string    `yaml:"include"` // For loading from files
}

ToolDef is a DSL tool definition.

type ToolImpl

type ToolImpl struct {
	Type    string            `yaml:"type"` // http, exec, file_read, file_write, builtin
	Method  string            `yaml:"method"`
	URL     string            `yaml:"url"`
	Headers map[string]string `yaml:"headers"`
	Query   map[string]string `yaml:"query"`
	Body    any               `yaml:"body"`
	Command string            `yaml:"command"`
	Timeout string            `yaml:"timeout"`
}

ToolImpl defines tool implementation.

type ToolParam

type ToolParam struct {
	Name        string   `yaml:"name"`
	Type        string   `yaml:"type"`
	Description string   `yaml:"description"`
	Required    bool     `yaml:"required"`
	Default     any      `yaml:"default"`
	Enum        []string `yaml:"enum"`
}

ToolParam defines a tool parameter.

type TracingDef

type TracingDef struct {
	Enabled  bool   `yaml:"enabled"`
	Exporter string `yaml:"exporter"` // otlp, jaeger, json
	Endpoint string `yaml:"endpoint"`
}

TracingDef is DSL tracing configuration.

type TriggerDef added in v0.7.13

type TriggerDef struct {
	On     string `yaml:"on" json:"on"`
	Where  string `yaml:"where,omitempty" json:"where,omitempty"`
	Gate   string `yaml:"gate,omitempty" json:"gate,omitempty"`
	Prompt string `yaml:"prompt" json:"prompt"`
}

TriggerDef declares one reactive subscription in the DSL: when an event of type `on` (a glob like "agent.*") arrives and its optional `where` predicate holds, the agent wakes with `prompt` rendered against the event. `gate` selects the salience tier ("" = rules only, "model" = cheap classifier).

type ValidationError

type ValidationError struct {
	File    string
	Line    int
	Column  int
	Field   string
	Message string
	Hint    string
}

ValidationError provides detailed DSL validation errors.

func (*ValidationError) Error

func (e *ValidationError) Error() string

type Workflow

type Workflow struct {
	Description string            `yaml:"description"`
	Inputs      map[string]*Input `yaml:"inputs"`
	Steps       []Step            `yaml:"steps"`
	Output      any               `yaml:"output"` // string or map
}

Workflow represents a workflow definition in the DSL.

Jump to

Keyboard shortcuts

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