a2a

package
v0.218.0 Latest Latest
Warning

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

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

README

a2a

What - the Agent2Agent anti-corruption layer: discovering remote agents, submitting tasks to them, and polling their status and artifacts. Why - the A2A protocol and its Go ADK are a foreign model, so they are translated here instead of leaking agent cards and task lifecycles into the CLI. How - infrastructure/ wraps the ADK client and agent cards, domain/ holds the CLI's own agent and task model, and the tools return normal tool results.

How it plugs in

  • NewTools(...) builds A2A_SubmitTask, A2A_QueryAgent and A2A_QueryTask from the manifests in tools/. Their approval is set under a2a.tools.*.
  • Submitted tasks are tracked by the job supervisor and polled until they finish. A2A_SubmitTask downloads the artifacts itself when a2a.task.artifacts_auto_download is on. Otherwise it tells the model to fetch them with WebFetch.
  • AgentSupervisor starts the configured local agent containers. Agents are declared in agents.yaml, and the feature is gated by the a2a config section.
  • The /agents and /tasks shortcuts read the same state.

Documentation

Index

Constants

View Source
const (
	ToolQueryAgent = "A2A_QueryAgent"
	ToolQueryTask  = "A2A_QueryTask"
	ToolSubmitTask = "A2A_SubmitTask"
)

Names of the A2A tools, as their manifests declare them.

View Source
const (
	// AgentContainerPrefix is the naming prefix for agent containers
	AgentContainerPrefix = "inference-agent-"
)

Variables

This section is empty.

Functions

func AgentNameFromURL

func AgentNameFromURL(url string) string

AgentNameFromURL derives a display name (the bare host) from an agent URL.

func AgentsPromptSection

func AgentsPromptSection(agents a2adomain.AgentCardService) string

AgentsPromptSection lists the configured A2A agents for the system prompt, so the model knows whom it can delegate to. Empty when there are none.

func ExternalAgents

func ExternalAgents(cfg *config.Config, agents *config.AgentsConfig) map[string]string

ExternalAgents returns the agents probed over the network rather than started here, keyed by display name. It mirrors A2AClient.GetConfiguredAgents: INFER_A2A_AGENTS when set (it overrides agents.yaml for the tools too), else the run: false entries of agents.yaml (run: true ones are probed as local).

func NewTools

NewTools builds the A2A tool set, empty unless a2a.enabled. Submitted tasks share the session's tracker, run as jobs of the supervisor behind jobs, and leave their outcome in retention once they finish.

func ToolNames

func ToolNames() []string

ToolNames returns the names of the A2A tools, whether or not config enables them, so a custom tool can never take one.

Types

type AgentStatus

type AgentStatus struct {
	Name  string `json:"name"`
	URL   string `json:"url"`
	State string `json:"state"`
	Error string `json:"error,omitempty"`
}

AgentStatus is the probe result for one configured A2A agent.

type AgentSupervisor

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

AgentSupervisor manages the lifecycle of A2A agent containers (local and external)

func NewAgentSupervisor

func NewAgentSupervisor(sessionID convdomain.SessionID, cfg *config.Config, agentsConfig *config.AgentsConfig, runtime containerruntime.ContainerRuntime, a2aService a2adomain.AgentCardService) *AgentSupervisor

NewAgentSupervisor creates the supervisor of the configured A2A agents

func (*AgentSupervisor) IsRunning

func (s *AgentSupervisor) IsRunning() bool

IsRunning returns whether any agents are running

func (*AgentSupervisor) SetPullProgressCallback

func (s *AgentSupervisor) SetPullProgressCallback(callback func(agentName string, done, total int))

SetPullProgressCallback sets the callback function for image pull progress updates

func (*AgentSupervisor) SetStatusCallback

func (s *AgentSupervisor) SetStatusCallback(callback func(agentName string, state a2adomain.AgentState, message string, url string, image string))

SetStatusCallback sets the callback function for agent status updates

func (*AgentSupervisor) StartAgent

func (s *AgentSupervisor) StartAgent(ctx context.Context, agent config.AgentEntry) error

StartAgent starts a single agent container with status updates

func (*AgentSupervisor) StartAgents

func (s *AgentSupervisor) StartAgents(ctx context.Context) error

StartAgents starts all local agents (run: true) and monitors external agents

func (*AgentSupervisor) StopAgent

func (s *AgentSupervisor) StopAgent(ctx context.Context, agentName string) error

StopAgent stops a single agent container

func (*AgentSupervisor) StopAgentByName

func (s *AgentSupervisor) StopAgentByName(ctx context.Context, agentName string) error

StopAgentByName stops this session's container for the agent even when this process did not start it. With the shared session id it stops the detached container started by `infer agents start`.

func (*AgentSupervisor) StopAgents

func (s *AgentSupervisor) StopAgents(ctx context.Context) error

StopAgents stops all running agent containers, cancels liveness probes, and cleans up the network

func (*AgentSupervisor) WaitForAgentsReady

func (s *AgentSupervisor) WaitForAgentsReady(ctx context.Context)

WaitForAgentsReady blocks until every run:true agent started by StartAgents has settled (ready or failed), or ctx is done. Headless mode calls this before the first LLM turn so the model never races an agent whose 3GB image is still pulling; failed agents settle too, so a broken agent can't block forever. Chat mode never calls it (the TUI streams status instead).

type AgentsStatusReport

type AgentsStatusReport struct {
	TotalAgents int           `json:"total_agents"`
	ReadyAgents int           `json:"ready_agents"`
	Agents      []AgentStatus `json:"agents"`
}

AgentsStatusReport mirrors the TUI's "A2A: ready/total" indicator plus a per-agent breakdown.

func ProbeAgents

func ProbeAgents(ctx context.Context, agents []config.AgentEntry, externalURLs []string) AgentsStatusReport

ProbeAgents fetches each agent's card once, the same check the liveness probes use, and reports what a fresh session would see. Local run:true agents are only reachable while a session (or a detached container) has them running.

type BackgroundTaskService

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

BackgroundTaskService handles background task operations (A2A-specific) Only instantiated when A2A tools are enabled

func NewBackgroundTaskService

func NewBackgroundTaskService(taskTracker a2adomain.TaskTracker, jobs jobController) *BackgroundTaskService

NewBackgroundTaskService creates a new background task service. jobs is the job supervisor - the single source of truth for which A2A tasks are running - while taskTracker still resolves the context graph and a task's agent URL for cancel.

func (*BackgroundTaskService) CancelBackgroundTask

func (s *BackgroundTaskService) CancelBackgroundTask(taskID string) error

CancelBackgroundTask cancels a background task by task ID

func (*BackgroundTaskService) GetBackgroundTasks

func (s *BackgroundTaskService) GetBackgroundTasks() []a2adomain.TaskPollingState

GetBackgroundTasks returns the active A2A tasks from the job supervisor - the single source of truth shared with the status-bar indicator - so the /tasks active list and the indicator can no longer diverge.

type QueryAgentResult

type QueryAgentResult struct {
	AgentName string         `json:"agent_name"`
	Query     string         `json:"query"`
	Response  *adk.AgentCard `json:"response"`
	Success   bool           `json:"success"`
	Message   string         `json:"message"`
	Duration  time.Duration  `json:"duration"`
}

type QueryAgentTool

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

func NewQueryAgentTool

func NewQueryAgentTool(cfg *config.Config) *QueryAgentTool

func (*QueryAgentTool) Definition

func (t *QueryAgentTool) Definition() sdk.ChatCompletionTool

func (*QueryAgentTool) Execute

func (*QueryAgentTool) FormatForLLM

func (t *QueryAgentTool) FormatForLLM(result *agentdomain.ToolExecutionResult) string

func (*QueryAgentTool) FormatForUI

func (t *QueryAgentTool) FormatForUI(result *agentdomain.ToolExecutionResult) string

func (*QueryAgentTool) FormatPreview

func (t *QueryAgentTool) FormatPreview(result *agentdomain.ToolExecutionResult) string

func (*QueryAgentTool) FormatResult

func (t *QueryAgentTool) FormatResult(result *agentdomain.ToolExecutionResult, formatType agentdomain.FormatterType) string

func (*QueryAgentTool) IsEnabled

func (t *QueryAgentTool) IsEnabled() bool

func (*QueryAgentTool) Manifest

func (t *QueryAgentTool) Manifest() agentdomain.ToolManifest

Manifest returns the tool's manifest with its configured require_approval.

func (*QueryAgentTool) SelfGated

func (t *QueryAgentTool) SelfGated() bool

SelfGated implements agentdomain.SelfGatedTool: a2a.enabled, not tools.enabled, switches the A2A tools on.

func (*QueryAgentTool) ShouldAlwaysExpand

func (t *QueryAgentTool) ShouldAlwaysExpand() bool

func (*QueryAgentTool) ShouldCollapseArg

func (t *QueryAgentTool) ShouldCollapseArg(key string) bool

func (*QueryAgentTool) Validate

func (t *QueryAgentTool) Validate(args map[string]any) error

type QueryTaskResult

type QueryTaskResult struct {
	AgentName string        `json:"agent_name"`
	ContextID string        `json:"context_id"`
	TaskID    string        `json:"task_id"`
	Task      *adk.Task     `json:"task"`
	Success   bool          `json:"success"`
	Message   string        `json:"message"`
	Duration  time.Duration `json:"duration"`
}

type QueryTaskTool

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

func NewQueryTaskTool

func NewQueryTaskTool(cfg *config.Config, liveness scheddomain.JobLivenessReporter) *QueryTaskTool

func (*QueryTaskTool) Definition

func (t *QueryTaskTool) Definition() sdk.ChatCompletionTool

func (*QueryTaskTool) Execute

func (*QueryTaskTool) FormatForLLM

func (t *QueryTaskTool) FormatForLLM(result *agentdomain.ToolExecutionResult) string

func (*QueryTaskTool) FormatForUI

func (t *QueryTaskTool) FormatForUI(result *agentdomain.ToolExecutionResult) string

func (*QueryTaskTool) FormatPreview

func (t *QueryTaskTool) FormatPreview(result *agentdomain.ToolExecutionResult) string

func (*QueryTaskTool) FormatResult

func (t *QueryTaskTool) FormatResult(result *agentdomain.ToolExecutionResult, formatType agentdomain.FormatterType) string

func (*QueryTaskTool) IsEnabled

func (t *QueryTaskTool) IsEnabled() bool

func (*QueryTaskTool) Manifest

func (t *QueryTaskTool) Manifest() agentdomain.ToolManifest

Manifest returns the tool's manifest with its configured require_approval.

func (*QueryTaskTool) SelfGated

func (t *QueryTaskTool) SelfGated() bool

SelfGated implements agentdomain.SelfGatedTool: a2a.enabled, not tools.enabled, switches the A2A tools on.

func (*QueryTaskTool) ShouldAlwaysExpand

func (t *QueryTaskTool) ShouldAlwaysExpand() bool

func (*QueryTaskTool) ShouldCollapseArg

func (t *QueryTaskTool) ShouldCollapseArg(key string) bool

func (*QueryTaskTool) Validate

func (t *QueryTaskTool) Validate(args map[string]any) error

type SubmitTaskResult

type SubmitTaskResult struct {
	TaskID     string    `json:"task_id"`
	ContextID  string    `json:"context_id,omitempty"`
	AgentURL   string    `json:"agent_url"`
	State      string    `json:"state"`
	Message    string    `json:"message"`
	TaskResult string    `json:"task_result,omitempty"`
	Success    bool      `json:"success"`
	Task       *adk.Task `json:"task,omitempty"`
}

SubmitTaskResult represents the result of an A2A task operation

type SubmitTaskTool

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

SubmitTaskTool handles A2A task submission and management

func NewSubmitTaskTool

func NewSubmitTaskTool(cfg *config.Config, taskTracker a2adomain.TaskTracker, submitter scheddomain.JobSubmitter, retention a2adomain.TaskRetentionService) *SubmitTaskTool

NewSubmitTaskTool creates a new A2A task tool

func NewSubmitTaskToolWithClient

func NewSubmitTaskToolWithClient(cfg *config.Config, taskTracker a2adomain.TaskTracker, submitter scheddomain.JobSubmitter, retention a2adomain.TaskRetentionService, client client.A2AClient) *SubmitTaskTool

NewSubmitTaskToolWithClient creates a new A2A task tool with an injected client (for testing)

func (*SubmitTaskTool) Definition

func (t *SubmitTaskTool) Definition() sdk.ChatCompletionTool

Definition returns the tool definition for the LLM

func (*SubmitTaskTool) Execute

Execute submits a task to an A2A agent. The agent's latest tracked task is resumed only when it is input-required; otherwise the message opens a fresh context so independent tasks on the same agent run in parallel. A caller continues an earlier conversation deliberately by passing its context_id.

func (*SubmitTaskTool) FormatForLLM

func (t *SubmitTaskTool) FormatForLLM(result *agentdomain.ToolExecutionResult) string

FormatForLLM formats the result for LLM consumption with detailed information

func (*SubmitTaskTool) FormatForUI

func (t *SubmitTaskTool) FormatForUI(result *agentdomain.ToolExecutionResult) string

FormatForUI formats the result for UI display

func (*SubmitTaskTool) FormatPreview

func (t *SubmitTaskTool) FormatPreview(result *agentdomain.ToolExecutionResult) string

FormatPreview returns a short preview of the result for UI display

func (*SubmitTaskTool) FormatResult

func (t *SubmitTaskTool) FormatResult(result *agentdomain.ToolExecutionResult, formatType agentdomain.FormatterType) string

FormatResult formats tool execution results for different contexts

func (*SubmitTaskTool) IsEnabled

func (t *SubmitTaskTool) IsEnabled() bool

IsEnabled returns whether this tool is enabled

func (*SubmitTaskTool) Manifest

func (t *SubmitTaskTool) Manifest() agentdomain.ToolManifest

Manifest returns the tool's manifest with its configured require_approval.

func (*SubmitTaskTool) SelfGated

func (t *SubmitTaskTool) SelfGated() bool

SelfGated implements agentdomain.SelfGatedTool: a2a.enabled, not tools.enabled, switches the A2A tools on.

func (*SubmitTaskTool) ShouldAlwaysExpand

func (t *SubmitTaskTool) ShouldAlwaysExpand() bool

ShouldAlwaysExpand determines if tool results should always be expanded in UI

func (*SubmitTaskTool) ShouldCollapseArg

func (t *SubmitTaskTool) ShouldCollapseArg(key string) bool

ShouldCollapseArg determines if an argument should be collapsed in display

func (*SubmitTaskTool) Validate

func (t *SubmitTaskTool) Validate(args map[string]any) error

Validate checks if the tool arguments are valid

type TaskRetentionService

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

TaskRetentionService manages in-memory retention of completed/terminal A2A tasks

func NewTaskRetentionService

func NewTaskRetentionService(maxRetention int) *TaskRetentionService

NewTaskRetentionService creates a new task retention service

func (*TaskRetentionService) AddTask

func (t *TaskRetentionService) AddTask(task a2adomain.TaskInfo)

AddTask adds a terminal task (completed, failed, canceled, etc.) to retention

func (*TaskRetentionService) Clear

func (t *TaskRetentionService) Clear()

Clear removes all retained tasks

func (*TaskRetentionService) GetMaxRetention

func (t *TaskRetentionService) GetMaxRetention() int

GetMaxRetention returns the current maximum retention count

func (*TaskRetentionService) GetTasks

func (t *TaskRetentionService) GetTasks() []a2adomain.TaskInfo

GetTasks returns all retained tasks

func (*TaskRetentionService) SetMaxRetention

func (t *TaskRetentionService) SetMaxRetention(maxRetention int)

SetMaxRetention updates the maximum retention count

type TaskTracker

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

TaskTracker is the hierarchical (agent → context → task) a2adomain.TaskTracker.

func NewTaskTracker

func NewTaskTracker(jobs jobDiscarder) *TaskTracker

NewTaskTracker creates a new TaskTracker. jobs, when set, is the supervisor whose A2A jobs ClearAllAgents discards along with the graph.

func (*TaskTracker) AddTask

func (t *TaskTracker) AddTask(contextID, taskID string)

AddTask adds a server-generated task ID to a context

func (*TaskTracker) ClearAllAgents

func (t *TaskTracker) ClearAllAgents()

ClearAllAgents clears all tracked agents, contexts, tasks, and polling states, and discards the in-flight supervised A2A jobs, so a conversation clear or switch cannot leave orphaned pollers running (still counted in the status bar, listed in /tasks, and able to land a late completion note).

func (*TaskTracker) GetAgentForContext

func (t *TaskTracker) GetAgentForContext(contextID string) string

GetAgentForContext returns the agent URL for a given context ID

func (*TaskTracker) GetAllAgents

func (t *TaskTracker) GetAllAgents() []string

GetAllAgents returns all agent URLs being tracked

func (*TaskTracker) GetAllContexts

func (t *TaskTracker) GetAllContexts() []string

GetAllContexts returns all context IDs being tracked

func (*TaskTracker) GetContextForTask

func (t *TaskTracker) GetContextForTask(taskID string) string

GetContextForTask returns the context ID for a given task

func (*TaskTracker) GetContextsForAgent

func (t *TaskTracker) GetContextsForAgent(agentURL string) []string

GetContextsForAgent returns all context IDs for a specific agent

func (*TaskTracker) GetLatestContextForAgent

func (t *TaskTracker) GetLatestContextForAgent(agentURL string) string

GetLatestContextForAgent returns the most recently registered context for an agent

func (*TaskTracker) GetLatestTaskForContext

func (t *TaskTracker) GetLatestTaskForContext(contextID string) string

GetLatestTaskForContext returns the most recently added task for a context

func (*TaskTracker) GetPollingState

func (t *TaskTracker) GetPollingState(taskID string) *a2adomain.TaskPollingState

GetPollingState returns the current polling state for a task

func (*TaskTracker) GetPollingTasksForContext

func (t *TaskTracker) GetPollingTasksForContext(contextID string) []string

GetPollingTasksForContext returns all task IDs that are currently being polled for a context

func (*TaskTracker) GetTasksForContext

func (t *TaskTracker) GetTasksForContext(contextID string) []string

GetTasksForContext returns all task IDs for a specific context

func (*TaskTracker) HasContext

func (t *TaskTracker) HasContext(contextID string) bool

HasContext checks if a context ID is registered

func (*TaskTracker) HasTask

func (t *TaskTracker) HasTask(taskID string) bool

HasTask checks if a task ID exists

func (*TaskTracker) RegisterContext

func (t *TaskTracker) RegisterContext(agentURL, contextID string)

RegisterContext registers a server-generated context ID for an agent

func (*TaskTracker) RemoveContext

func (t *TaskTracker) RemoveContext(contextID string)

RemoveContext removes a context and all its tasks

func (*TaskTracker) RemoveTask

func (t *TaskTracker) RemoveTask(taskID string)

RemoveTask removes a task from its context

func (*TaskTracker) StartPolling

func (t *TaskTracker) StartPolling(taskID string, state *a2adomain.TaskPollingState)

StartPolling starts tracking a background polling operation for a task

func (*TaskTracker) StopPolling

func (t *TaskTracker) StopPolling(taskID string)

StopPolling stops and clears the polling state for a task

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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