Documentation
¶
Overview ¶
Package agent defines the core agent interfaces and types for Hector v2.
Agent Interface ¶
The Agent interface is the fundamental abstraction for all agents:
type Agent interface {
Name() string
Description() string
Run(InvocationContext) iter.Seq2[*Event, error]
SubAgents() []Agent
}
Context Hierarchy ¶
The package provides a three-tier context hierarchy:
- InvocationContext: Full access during agent execution
- ReadonlyContext: Read-only access for tools and callbacks
- CallbackContext: State modification for callbacks
Creating Agents ¶
Use the provided constructors to create agents:
agent, err := agent.New(agent.Config{
Name: "my-agent",
Description: "A helpful assistant",
Run: myRunFunc,
})
For LLM-based agents, use the llmagent subpackage:
agent, err := llmagent.New(llmagent.Config{
Name: "llm-agent",
Model: myModel,
Instruction: "You are a helpful assistant.",
})
Index ¶
- Constants
- func FindAgentPath(root Agent, name string) []string
- func WalkAgents(root Agent, visitor func(Agent, int) bool)
- type AfterAgentCallback
- type Agent
- type AgentType
- type ArtifactInfo
- type ArtifactListResponse
- type ArtifactLoadResponse
- type ArtifactSaveResponse
- type Artifacts
- type BeforeAgentCallback
- type CallbackContext
- type CancellableTask
- type Checkpointable
- type ChildExecution
- type Config
- type Content
- type Event
- type EventActions
- type Events
- type InvocationContext
- type InvocationContextParams
- type Memory
- type MemoryResult
- type MemorySearchResponse
- type ReadonlyContext
- type ReadonlyState
- type RunConfig
- type Session
- type State
- type StreamingMode
- type TempClearable
- type ThinkingState
- type ToolCallState
- type ToolResultState
Constants ¶
const ( // AuthorUser represents events authored by the user (human input). // Used when tool results or other events come from user interactions. AuthorUser = "user" // AuthorSystem represents events authored by the system. // Used for system-generated events like errors or notifications. AuthorSystem = "system" )
Event author constants
Variables ¶
This section is empty.
Functions ¶
func FindAgentPath ¶
FindAgentPath returns the path to an agent in the tree. The path is a slice of agent names from root to the target (exclusive of root). Returns nil if the agent is not found.
Example:
// For a tree: coordinator -> team_a -> specialist path := agent.FindAgentPath(coordinator, "specialist") // path = ["team_a", "specialist"]
func WalkAgents ¶
WalkAgents visits all agents in the tree depth-first. The visitor function is called for each agent with its depth level. If the visitor returns false, the walk stops.
Example:
agent.WalkAgents(root, func(ag Agent, depth int) bool {
fmt.Printf("%s%s\n", strings.Repeat(" ", depth), ag.Name())
return true // continue walking
})
Types ¶
type AfterAgentCallback ¶
type AfterAgentCallback func(CallbackContext) (*a2a.Message, error)
AfterAgentCallback is called after the agent completes. If it returns non-nil content or error, a new event is created.
type Agent ¶
type Agent interface {
// Name returns the unique identifier for this agent within the agent tree.
// Agent name cannot be "user" as it's reserved for end-user input.
Name() string
// DisplayName returns the human-readable name of the agent.
// Used for UI attribution.
DisplayName() string
// Description returns a human-readable description of the agent's capability.
// Used by LLMs to determine whether to delegate control to this agent.
Description() string
// Run executes the agent and yields events.
// The iterator pattern allows clean streaming of results.
Run(InvocationContext) iter.Seq2[*Event, error]
// SubAgents returns child agents that this agent can delegate to.
SubAgents() []Agent
// Type returns the agent type for introspection.
// Used by the runner to determine workflow vs delegation semantics.
Type() AgentType
}
Agent is the base interface which all agents must implement.
Agents are created with constructors to ensure correct initialization:
- agent.New for custom agents
- llmagent.New for LLM-based agents
- remoteagent.NewA2A for remote A2A agents
- workflowagents for sequential/parallel/loop patterns
func FindAgent ¶
FindAgent searches for an agent by name in the agent tree. It performs a depth-first search starting from the root agent.
This provides the same functionality as ADK-Go's find_agent() method.
Example:
root, _ := llmagent.New(llmagent.Config{
Name: "coordinator",
SubAgents: []agent.Agent{researcher, writer},
})
// Find a descendant by name
found := agent.FindAgent(root, "researcher")
if found != nil {
// Use the found agent
}
func ListAgents ¶
ListAgents returns a flat list of all agents in the tree. The root agent is included first, followed by descendants depth-first.
type ArtifactInfo ¶
ArtifactInfo describes a stored artifact.
type ArtifactListResponse ¶
type ArtifactListResponse struct {
Artifacts []ArtifactInfo
}
ArtifactListResponse is returned when listing artifacts.
type ArtifactLoadResponse ¶
ArtifactLoadResponse is returned when loading an artifact.
type ArtifactSaveResponse ¶
ArtifactSaveResponse is returned when saving an artifact.
type Artifacts ¶
type Artifacts interface {
Save(ctx context.Context, name string, part a2a.Part) (*ArtifactSaveResponse, error)
List(ctx context.Context) (*ArtifactListResponse, error)
Load(ctx context.Context, name string) (*ArtifactLoadResponse, error)
LoadVersion(ctx context.Context, name string, version int) (*ArtifactLoadResponse, error)
}
Artifacts provides artifact storage operations.
type BeforeAgentCallback ¶
type BeforeAgentCallback func(CallbackContext) (*a2a.Message, error)
BeforeAgentCallback is called before the agent starts. If it returns non-nil content or error, agent run is skipped.
type CallbackContext ¶
type CallbackContext interface {
ReadonlyContext
// Artifacts returns the artifact service.
Artifacts() Artifacts
// State returns mutable session state.
State() State
}
CallbackContext provides state modification for callbacks.
type CancellableTask ¶
type CancellableTask interface {
// RegisterExecution registers a child execution for cascade cancellation.
RegisterExecution(exec *ChildExecution)
// UnregisterExecution removes a child execution from tracking.
UnregisterExecution(callID string)
// CancelExecution cancels a specific child execution.
CancelExecution(callID string) bool
// GetID returns the task ID.
GetID() string
}
CancellableTask provides task-level cancellation support. Defined in agent package to avoid circular imports with pkg/task. The task.Task type implements this interface.
type Checkpointable ¶
type Checkpointable interface {
Agent
// CaptureCheckpointState returns the agent's current execution state.
// Called by the checkpoint manager at strategic points (pre-LLM, post-tool, etc.)
CaptureCheckpointState() (map[string]any, error)
// RestoreCheckpointState restores the agent's execution state from a checkpoint.
// Called by the recovery manager when resuming from a checkpoint.
RestoreCheckpointState(state map[string]any) error
}
Checkpointable is an optional interface for agents that support state checkpointing.
Agents implementing this interface can have their execution state captured for fault tolerance and HITL workflow recovery.
Implementation Note (ported from legacy Hector):
Checkpoints capture the state of the CURRENTLY EXECUTING agent only. The full multi-agent history is preserved in session events (the source of truth). On recovery: 1. Checkpoint identifies which agent was active 2. Session events provide full conversation history 3. Runner.findAgentToRun() routes to the correct agent
Not all agents need to implement this - only agents with internal state that cannot be reconstructed from session events alone.
type ChildExecution ¶
type ChildExecution struct {
// CallID is the unique identifier for this execution.
CallID string
// Name is the tool or agent name.
Name string
// Type is either "tool" or "agent".
Type string
// Cancel is called to cancel this execution.
Cancel func() bool
}
ChildExecution represents an active tool or sub-agent execution. Used for cascade cancellation when a task is cancelled.
type Config ¶
type Config struct {
// Name must be a non-empty string, unique within the agent tree.
Name string
// DisplayName is the human-readable name (optional).
DisplayName string
// Description of the agent's capability (used for delegation decisions).
Description string
// SubAgents are child agents this agent can delegate tasks to.
SubAgents []Agent
// BeforeAgentCallbacks are called before the agent starts its run.
// If any returns non-nil content or error, agent run is skipped.
BeforeAgentCallbacks []BeforeAgentCallback
// Run defines the agent's execution logic.
Run func(InvocationContext) iter.Seq2[*Event, error]
// AgentType allows specifying the agent type (optional).
// If empty, defaults to TypeCustomAgent.
AgentType AgentType
// AfterAgentCallbacks are called after the agent completes its run.
AfterAgentCallbacks []AfterAgentCallback
}
Config is the configuration for creating a new custom Agent.
type Content ¶
type Content struct {
Parts []a2a.Part
Role a2a.MessageRole
}
Content is a convenience type for building message content.
func NewTextContent ¶
func NewTextContent(text string, role a2a.MessageRole) *Content
NewTextContent creates content with a text part.
type Event ¶
type Event struct {
// ID is the unique identifier for this event.
ID string
// Timestamp when the event was created.
Timestamp time.Time
// InvocationID links this event to its invocation.
InvocationID string
// Branch isolates conversation history for parallel agents.
// Format: "agent_1.agent_2.agent_3" (parent chain).
Branch string
// Author is the display name of the agent (or "user"/"system").
// This is used for UI rendering and attribution.
Author string
// AgentID is the unique identifier of the agent that produced this event.
// Used for internal routing, logic, and state tracking.
AgentID string
// Message contains the A2A message content (text, files, data).
// This maps directly to a2a.Message for seamless translation.
Message *a2a.Message
// Actions captures side effects (state changes, transfers, etc).
Actions EventActions
// LongRunningToolIDs identifies tools awaiting external completion.
LongRunningToolIDs []string
// Partial indicates this is a streaming chunk, not a complete event.
Partial bool
// TurnComplete indicates this is the final event of a turn.
TurnComplete bool
// Interrupted indicates this event was cut off due to cancellation or timeout.
// When true, the response may be incomplete. This helps distinguish between:
// - A complete response that ended naturally (Interrupted=false)
// - A partial response that was forcibly stopped (Interrupted=true)
Interrupted bool
// ErrorCode is a machine-readable error identifier (e.g., "rate_limit", "timeout").
ErrorCode string
// ErrorMessage is a human-readable error description.
ErrorMessage string
// Thinking captures the model's reasoning process (for thinking-enabled models).
// This is rendered as a collapsible ThinkingWidget in the UI.
Thinking *ThinkingState
// ToolCalls captures tool invocations in this event.
// Each tool call is rendered as a ToolWidget in the UI.
ToolCalls []ToolCallState
// ToolResults captures tool execution results in this event.
// These update the corresponding ToolWidget status.
ToolResults []ToolResultState
// CustomMetadata for application-specific data.
CustomMetadata map[string]any
// OnPersisted is a callback invoked after the event is persisted to the session.
// Used by async agents (like ParallelAgent) to synchronize with the persistence layer.
// This field is not serialized.
OnPersisted func() `json:"-"`
}
Event represents an interaction in an agent conversation. Events are yielded by Agent.Run() and translated to A2A events by the server.
func (*Event) HasToolCalls ¶
HasToolCalls returns true if this event contains tool call requests. Tool calls indicate the LLM wants to execute tools before providing a final response.
func (*Event) HasToolResults ¶
HasToolResults returns true if this event contains tool execution results. Tool results indicate tools have been executed and the LLM needs to process them.
func (*Event) IsFinalResponse ¶
IsFinalResponse returns whether this event is a final response. Multiple events can be final when multiple agents participate in one invocation.
An event is NOT final if it: - Contains function/tool calls (awaiting execution) - Contains function/tool responses (awaiting LLM summarization) - Is a partial/streaming event
func (*Event) TextContent ¶
TextContent extracts text content from the event's message.
type EventActions ¶
type EventActions struct {
// StateDelta contains key-value changes to session state.
StateDelta map[string]any
// ArtifactDelta tracks artifact updates (filename -> version).
ArtifactDelta map[string]int64
// SkipSummarization prevents LLM summarization of tool responses.
SkipSummarization bool
// TransferToAgent requests control transfer to another agent.
TransferToAgent string
// Escalate requests escalation to a higher-level agent.
Escalate bool
// RequireInput signals that human input is required (HITL pattern).
// When true, the task transitions to `input_required` state.
// This is used by long-running tools that need approval or additional info.
RequireInput bool
// InputPrompt is the message shown to the human when RequireInput is true.
// Should explain what input is needed and why.
InputPrompt string
}
EventActions represents side effects attached to an event.
type InvocationContext ¶
type InvocationContext interface {
// Embed CallbackContext which embeds ReadonlyContext
// This allows InvocationContext to be used wherever ReadonlyContext
// or CallbackContext is expected.
CallbackContext
// Agent returns the current agent being executed.
Agent() Agent
// Session returns the session for this invocation.
Session() Session
// Memory provides access to cross-session memory.
Memory() Memory
// RunConfig returns the runtime configuration for this invocation.
RunConfig() *RunConfig
// EndInvocation signals that the invocation should stop.
EndInvocation()
// Ended returns whether the invocation has been ended.
Ended() bool
}
InvocationContext represents the context of an agent invocation.
An invocation:
- Starts with a user message and ends with a final response.
- Can contain one or multiple agent calls.
- Is handled by runner.Run().
An agent call:
- Is handled by agent.Run().
- Ends when agent.Run() completes.
An agent call can contain multiple steps (LLM calls + tool executions).
┌─────────────────────── invocation ──────────────────────────┐ ┌──────────── llm_agent_call_1 ────────────┐ ┌─ agent_call_2 ─┐ ┌──── step_1 ────────┐ ┌───── step_2 ──────┐ [call_llm] [call_tool] [call_llm] [transfer]
func NewInvocationContext ¶
func NewInvocationContext(ctx context.Context, params InvocationContextParams) InvocationContext
NewInvocationContext creates a new InvocationContext.
type InvocationContextParams ¶
type InvocationContextParams struct {
Artifacts Artifacts
Memory Memory
Session Session
Agent Agent
Branch string
UserContent *Content
RunConfig *RunConfig
}
InvocationContextParams contains parameters for creating an InvocationContext.
type Memory ¶
type Memory interface {
AddSession(ctx context.Context, session Session) error
Search(ctx context.Context, query string) (*MemorySearchResponse, error)
}
Memory provides cross-session memory operations.
type MemoryResult ¶
MemoryResult is a single memory search result.
type MemorySearchResponse ¶
type MemorySearchResponse struct {
Results []MemoryResult
}
MemorySearchResponse contains memory search results.
type ReadonlyContext ¶
type ReadonlyContext interface {
context.Context
// InvocationID returns the unique ID for this invocation.
InvocationID() string
// AgentName returns the current agent's name.
AgentName() string
// UserContent returns the user message that started this invocation.
UserContent() *Content
// ReadonlyState returns read-only access to session state.
ReadonlyState() ReadonlyState
// UserID returns the user identifier.
UserID() string
// AppName returns the application name.
AppName() string
// SessionID returns the session identifier.
SessionID() string
// Branch returns the agent hierarchy path.
Branch() string
}
ReadonlyContext provides read-only access to invocation data. Safe to pass to tools and external code.
type ReadonlyState ¶
ReadonlyState provides read-only access to session state.
type RunConfig ¶
type RunConfig struct {
// StreamingMode controls event streaming behavior.
StreamingMode StreamingMode
// SaveInputBlobsAsArtifacts saves file inputs as artifacts.
SaveInputBlobsAsArtifacts bool
// Task provides access to the parent task for cascade cancellation.
// This is set by the executor when a task is associated with the invocation.
Task CancellableTask
// SkipAppendUserMessage skips appending the user message to session.
// Used for checkpoint recovery where the message already exists in history.
SkipAppendUserMessage bool
}
RunConfig contains runtime configuration for an invocation.
type Session ¶
type Session interface {
ID() string
AppName() string
UserID() string
State() State
Events() Events
}
Session represents a conversation session. Defined here to avoid circular imports with session package.
type State ¶
type State interface {
Get(key string) (any, error)
Set(key string, value any) error
Delete(key string) error
All() iter.Seq2[string, any]
}
State is a mutable key-value store for session state.
type StreamingMode ¶
type StreamingMode string
StreamingMode controls how events are streamed.
const ( StreamingModeNone StreamingMode = "none" StreamingModeSSE StreamingMode = "sse" StreamingModeFull StreamingMode = "full" )
type TempClearable ¶
type TempClearable interface {
// ClearTempKeys removes all keys with the "temp:" prefix.
// Called automatically after each invocation completes.
ClearTempKeys()
}
TempClearable is implemented by state stores that support clearing temp keys.
type ThinkingState ¶
type ThinkingState struct {
// ID uniquely identifies this thinking block within a conversation.
ID string `json:"id"`
// Status indicates the lifecycle state: "active" | "completed".
Status string `json:"status"`
// Content is the thinking text (may stream incrementally).
Content string `json:"content"`
// Signature is used for multi-turn verification (e.g., Anthropic).
Signature string `json:"signature,omitempty"`
// Type categorizes the thinking: "default" | "planning" | "reflection" | "goal".
Type string `json:"type,omitempty"`
}
ThinkingState represents the model's reasoning process. Maps to ThinkingWidget in the UI with proper lifecycle animations.
type ToolCallState ¶
type ToolCallState struct {
// ID uniquely identifies this tool call (matches LLM's tool_use ID).
ID string `json:"id"`
// Name is the tool being called.
Name string `json:"name"`
// Args are the arguments passed to the tool.
Args map[string]any `json:"args"`
// Status indicates lifecycle: "pending" | "working".
Status string `json:"status"`
}
ToolCallState represents a tool invocation. Maps to ToolWidget in the UI with "working" status.
type ToolResultState ¶
type ToolResultState struct {
// ToolCallID links this result to its ToolCallState.
ToolCallID string `json:"tool_call_id"`
// Content is the tool's output.
Content string `json:"content"`
// Status indicates outcome: "success" | "failed".
Status string `json:"status"`
// IsError indicates if Content represents an error message.
IsError bool `json:"is_error,omitempty"`
}
ToolResultState represents a tool execution result. Updates the corresponding ToolWidget to "success" | "failed".
Directories
¶
| Path | Synopsis |
|---|---|
|
Package llmagent provides an LLM-based agent implementation for Hector v2.
|
Package llmagent provides an LLM-based agent implementation for Hector v2. |
|
Package remoteagent provides remote A2A agent support.
|
Package remoteagent provides remote A2A agent support. |
|
Package runneragent provides a deterministic tool execution agent.
|
Package runneragent provides a deterministic tool execution agent. |
|
Package workflowagent provides workflow agents for orchestrating multi-agent flows.
|
Package workflowagent provides workflow agents for orchestrating multi-agent flows. |