Documentation
¶
Overview ¶
Package agent is the gridctl agent runtime. It hosts typed graph composition (via the internal/eino adapter), an LLM provider abstraction, the typed Skill SDK, the multi-agent orchestrator, and JSONL run persistence. The runtime sits on top of the existing MCP gateway: tool calls flow through pkg/mcp.Gateway so existing tracing, pricing, replica routing, vault auth, and tool whitelisting apply unchanged.
This file ships the public type surface that the rest of pkg/agent (and downstream callers) build against. The wrappers around cloudwego/eino live in pkg/agent/internal/eino — that boundary is where reversibility lives, and is enforced in CI by scripts/check-eino-boundary.sh.
Index ¶
Constants ¶
const END = einoadapter.END
END is the implicit graph exit vertex. Use it as the destination argument to AddEdge to surface a node's output as the graph's output.
const START = einoadapter.START
START is the implicit graph entry vertex. Use it as the source argument to AddEdge to receive the graph's input.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ChatChunk ¶
type ChatChunk struct {
// Delta is appended text since the last chunk. Empty for chunks
// that only carry tool-call deltas, usage, or stop information.
Delta string `json:"delta,omitempty"`
// ToolCallDelta carries an incremental update to a tool call.
// Empty when the chunk only carries text or end-of-stream
// metadata.
ToolCallDelta *ToolCallDelta `json:"tool_call_delta,omitempty"`
// Usage is populated only on the final chunk of the stream when
// the provider reports usage at the end (Anthropic and OpenAI
// both do; Gemini reports per-chunk usage that the runtime
// accumulates).
Usage *Usage `json:"usage,omitempty"`
// StopReason is populated on the final chunk when generation
// ended cleanly. Empty on intermediate chunks.
StopReason StopReason `json:"stop_reason,omitempty"`
}
ChatChunk is a single delta in a streaming Provider response. Providers emit chunks in the order they arrive on the wire; the runtime is responsible for accumulating Content across token chunks and stitching ToolCallDelta entries into complete ToolCalls before surfacing them.
type ChatModel ¶
type ChatModel interface {
Generate(ctx context.Context, req ChatRequest) (ChatResponse, error)
Stream(ctx context.Context, req ChatRequest) (*StreamReader[ChatChunk], error)
}
ChatModel is the gridctl-shaped LLM provider surface. Each Phase B provider package implements this interface; the agent runtime only ever depends on it. Generate is the synchronous shape; Stream returns a typed reader whose Close MUST be invoked by the caller.
type ChatRequest ¶
type ChatRequest struct {
// Model is the canonical model ID (e.g. "claude-opus-4-7",
// "gpt-4o", "gemini-2.0-flash"). Provider packages reject IDs
// outside their family.
Model string `json:"model"`
// Messages are the conversation history in order. The last
// message is the active turn.
Messages []Message `json:"messages"`
// System is an optional conversation-level system prompt.
// Providers that take a top-level `system` field populate that
// field; providers without one prepend a system-role message.
System string `json:"system,omitempty"`
// Tools is the catalog the model may invoke. Empty disables tool
// use. Each provider translates ToolInfo to its own catalog
// shape.
Tools []ToolInfo `json:"tools,omitempty"`
// Temperature is the sampling temperature. Zero means "use the
// provider default"; explicit zero is not addressable through
// this field. Negative values are rejected at the provider layer.
Temperature float64 `json:"temperature,omitempty"`
// MaxTokens is the maximum number of tokens the model may emit.
// Zero means "use the provider default" (Anthropic requires a
// value; the provider supplies one).
MaxTokens int `json:"max_tokens,omitempty"`
// StopSequences are textual sequences that, when generated, end
// the model's turn. Providers translate verbatim.
StopSequences []string `json:"stop_sequences,omitempty"`
}
ChatRequest is the gridctl-shaped LLM request envelope. Providers translate it to their wire formats. Required fields: Model and Messages. System is the conversation-level system prompt; providers that take a top-level `system` field (Anthropic) populate that field, providers that take a system-role message (OpenAI, Gemini) prepend a message instead.
type ChatResponse ¶
type ChatResponse struct {
// Model is the canonical model ID the provider actually served
// the call with. May differ from ChatRequest.Model when the
// provider auto-substitutes (e.g. "claude-3-5-sonnet-latest" →
// dated revision).
Model string `json:"model"`
// Content is the textual body of the assistant turn. Empty when
// the turn consisted only of tool-use blocks.
Content string `json:"content,omitempty"`
// ToolCalls are the tool invocations the model wants the runtime
// to perform. The runtime is responsible for executing them and
// feeding the results back through subsequent ChatRequests.
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
// StopReason is the gridctl-shaped reason generation ended.
StopReason StopReason `json:"stop_reason"`
// Usage is the per-call token accounting.
Usage Usage `json:"usage"`
}
ChatResponse is the gridctl-shaped LLM response envelope returned by Provider.Generate. Streamed responses deliver the same data through ChatChunk; see Provider.Stream.
type Graph ¶
type Graph[I, O any] = einoadapter.Graph[I, O]
Graph is a typed graph composition that compiles into a Runnable. The underlying composition library is hidden behind the adapter boundary; callers interact only with this gridctl-shaped surface.
type Message ¶
type Message struct {
// Role is "system", "user", "assistant", or "tool".
Role Role `json:"role"`
// Content is the textual body of the message. Empty when an
// assistant message contains only ToolCalls.
Content string `json:"content,omitempty"`
// ToolCalls are the tool invocations an assistant message asks
// the runtime to perform. Populated only for Role == RoleAssistant.
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
// ToolCallID is the ID of the tool call this message answers.
// Populated only for Role == RoleTool. Must reference a prior
// assistant ToolCall.ID in the same conversation.
ToolCallID string `json:"tool_call_id,omitempty"`
// Name is the tool name for tool-result messages. Some providers
// (notably Anthropic) require the tool name on the result block;
// others (OpenAI, Gemini) ignore it. Required when Role == RoleTool.
Name string `json:"name,omitempty"`
}
Message is a single chat-message exchanged with a Provider. A message either carries human/assistant text content, tool-call requests (assistant), or a tool-call result (tool). Cross-provider translation is the responsibility of each provider package.
type Role ¶
type Role string
Role is a chat-message role used by ChatRequest.Messages. Providers translate roles to their wire representations. The vocabulary is intentionally narrow; provider adapters reject unknown roles rather than silently coercing them.
const ( // RoleSystem is a system instruction. Anthropic surfaces this // through the top-level `system` field rather than a message; // providers translate accordingly. RoleSystem Role = "system" // RoleUser is a user-authored message. RoleUser Role = "user" // RoleAssistant is a model-authored message. RoleAssistant Role = "assistant" // RoleTool is a tool-result message attached to a prior assistant // tool_call. The ToolCallID field references the call. RoleTool Role = "tool" )
type Runnable ¶
type Runnable[I, O any] = einoadapter.Runnable[I, O]
Runnable is a compiled, executable graph. It exposes Invoke for synchronous execution and Stream for chunked streaming output.
type StopReason ¶
type StopReason string
StopReason describes why a model stopped generating. Each provider maps its native stop-reason vocabulary to one of these values; the compose graph and UI both depend on the gridctl-shaped form.
const ( // StopReasonEnd is a natural end of generation. StopReasonEnd StopReason = "end" // StopReasonMaxTokens is the model hitting MaxTokens before // finishing. StopReasonMaxTokens StopReason = "max_tokens" // StopReasonToolUse is the model emitting a tool_use stop, which // the runtime must satisfy with tool results before resuming. StopReasonToolUse StopReason = "tool_use" // StopReasonStopSequence is the model hitting a configured stop // sequence. StopReasonStopSequence StopReason = "stop_sequence" // StopReasonError is a provider-side error that aborted // generation. The accompanying response carries the error text. StopReasonError StopReason = "error" )
type StreamReader ¶
type StreamReader[T any] = einoadapter.StreamReader[T]
StreamReader emits typed chunks from a streaming Runnable. Recv returns io.EOF on stream completion; callers are responsible for Close.
func StreamReaderFromSlice ¶
func StreamReaderFromSlice[T any](items []T) *StreamReader[T]
StreamReaderFromSlice wraps a slice as a StreamReader. Phase B provider adapters use it to bridge non-streaming responses into the streaming interface; tests use it for fixtures.
type ToolCall ¶
type ToolCall struct {
// ID is the provider-issued tool-call identifier. Required so
// tool-result messages can reference the originating call.
ID string `json:"id"`
// Name is the tool name (no server prefix; the gateway prefixes
// when needed).
Name string `json:"name"`
// Arguments is the JSON-encoded argument object as the model
// emitted it. Callers MUST validate against the tool's input
// schema before invoking; raw JSON is preserved verbatim so
// provider quirks (key ordering, escaping) are visible.
Arguments json.RawMessage `json:"arguments"`
}
ToolCall is a model-issued request to invoke a tool. The runtime resolves Arguments against the tool's input schema, then invokes the tool through the gateway via a ToolCaller. Each provider package translates its native tool-use representation to/from this shape so the compose graph never sees provider-specific tool formats.
type ToolCallDelta ¶
type ToolCallDelta struct {
// Index identifies which tool call this delta belongs to. Tool
// calls are emitted in declaration order (0, 1, 2, ...).
Index int `json:"index"`
// ID is the tool-call identifier. Populated on the first delta
// for an index.
ID string `json:"id,omitempty"`
// Name is the tool name. Populated on the first delta for an
// index.
Name string `json:"name,omitempty"`
// ArgsDelta is a partial JSON fragment for the call's Arguments.
// Concatenating all ArgsDelta values for a given Index yields the
// final Arguments JSON.
ArgsDelta string `json:"args_delta,omitempty"`
}
ToolCallDelta is an incremental update to a single ToolCall during streaming. Providers emit Index to identify which call the delta belongs to (the same call may receive multiple deltas across many chunks). On the first delta for a given Index, ID and Name are populated; subsequent deltas carry only ArgsDelta (a partial JSON fragment for Arguments).
type ToolCallResult ¶
type ToolCallResult = mcp.ToolCallResult
ToolCallResult is the gridctl-shaped result envelope returned by a ToolCaller. It is a type alias of mcp.ToolCallResult so the agent runtime and the gateway speak the same vocabulary — the runtime is layered on top of the gateway, not parallel to it. Phase C extends the gateway's CallTool path to expose typed Skill results through this same envelope; see pkg/registry/server.go.
type ToolCaller ¶
type ToolCaller interface {
CallTool(ctx context.Context, name string, arguments map[string]any) (*ToolCallResult, error)
}
ToolCaller invokes tools across the gateway's aggregated servers. It mirrors mcp.ToolCaller exactly so a *mcp.Gateway satisfies the interface; the wrapper in pkg/agent/gateway exists to convert the import direction (agent depends on mcp; mcp does not depend on agent) and to give the runtime a place to attach observability that only matters for agent-initiated calls.
type ToolInfo ¶
type ToolInfo struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
InputSchema json.RawMessage `json:"input_schema,omitempty"`
}
ToolInfo is the gridctl-shaped tool descriptor used across the agent runtime. It is intentionally derivable from pkg/mcp.Tool: a registered typed skill becomes a tool in the same envelope the gateway already routes for any other MCP tool, and an upstream client that points at a gridctl gateway sees the same shape whether the tool is implemented as a typed Go skill, a TS skill, or a downstream MCP server.
Defined here, not in pkg/mcp, to keep Phase A from touching pkg/mcp. Phase C reconciles the two when the registry walker grows to recognise typed-skill metadata; for now the structural overlap is intentional.
type ToolResult ¶
type ToolResult struct {
// ToolCallID references the assistant message's ToolCall.ID.
ToolCallID string `json:"tool_call_id"`
// Name is the tool name. Some providers require it on the result.
Name string `json:"name,omitempty"`
// Output is the textual content surfaced to the model. The runtime
// renders gateway ToolCallResult.Content into a single string here;
// structured-content support lands in a follow-up.
Output string `json:"output"`
// IsError reports whether the tool invocation produced an error.
// Providers map this to their error-flag conventions (Anthropic
// `is_error: true`, OpenAI tool error message, Gemini error part).
IsError bool `json:"is_error,omitempty"`
}
ToolResult is the runtime's reply to a ToolCall after the gateway has invoked the tool. Providers translate this into their tool-result wire shape (Anthropic `tool_result` content block, OpenAI tool role message, Gemini function-response part).
type Usage ¶
type Usage struct {
// InputTokens is the count of prompt tokens billed at the input
// rate. Excludes cache-read tokens, which are priced separately.
InputTokens int `json:"input_tokens"`
// OutputTokens is the count of generated tokens billed at the
// output rate.
OutputTokens int `json:"output_tokens"`
// CacheReadTokens is the count of input tokens served from a
// prompt cache. Anthropic and OpenAI both report this; Gemini
// surfaces it through cached_content_token_count.
CacheReadTokens int `json:"cache_read_tokens,omitempty"`
// CacheWriteTokens is the count of input tokens written to a
// prompt cache (Anthropic-only on the providers we cover).
CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
}
Usage is the per-call token accounting reported by a Provider. Cache fields default to zero when the provider does not surface cache usage. Gateway-level cost recording prices the four components independently — see pkg/pricing.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package compose hosts the agent runtime's graph-level primitives that sit just above the eino adapter — primitives the rest of pkg/agent composes against without ever importing eino types directly.
|
Package compose hosts the agent runtime's graph-level primitives that sit just above the eino adapter — primitives the rest of pkg/agent composes against without ever importing eino types directly. |
|
dev
|
|
|
devserver
Package devserver hosts the HTTP surface the agent IDE talks to.
|
Package devserver hosts the HTTP surface the agent IDE talks to. |
|
parser
Package parser extracts a flat node list from a typed-skill source file.
|
Package parser extracts a flat node list from a typed-skill source file. |
|
scaffold
Package scaffold renders the starter files `gridctl agent init` drops into a fresh project.
|
Package scaffold renders the starter files `gridctl agent init` drops into a fresh project. |
|
watcher
Package watcher recursively watches a project directory for typed-skill source changes and pushes events to subscribers.
|
Package watcher recursively watches a project directory for typed-skill source changes and pushes events to subscribers. |
|
Package gateway adapts the existing pkg/mcp.Gateway into the agent.ToolCaller surface the runtime invokes during agentic loops.
|
Package gateway adapts the existing pkg/mcp.Gateway into the agent.ToolCaller surface the runtime invokes during agentic loops. |
|
internal
|
|
|
eino
Package eino is the boundary between gridctl's agent runtime and the upstream cloudwego/eino library.
|
Package eino is the boundary between gridctl's agent runtime and the upstream cloudwego/eino library. |
|
Package llm hosts the gridctl LLM provider abstraction.
|
Package llm hosts the gridctl LLM provider abstraction. |
|
anthropic
Package anthropic implements agent.ChatModel against the Anthropic Messages API.
|
Package anthropic implements agent.ChatModel against the Anthropic Messages API. |
|
gateway
Package gateway is the LLM-side passthrough provider.
|
Package gateway is the LLM-side passthrough provider. |
|
google
Package google implements agent.ChatModel against the Google Gemini Generative Language API.
|
Package google implements agent.ChatModel against the Google Gemini Generative Language API. |
|
observed
Package observed wraps an agent.ChatModel with the gridctl observability surface — OTel spans, pricing.CalculateBreakdown for USD cost, and metrics.Accumulator.RecordCost with a synthetic provider name (no MCP envelope spoofing).
|
Package observed wraps an agent.ChatModel with the gridctl observability surface — OTel spans, pricing.CalculateBreakdown for USD cost, and metrics.Accumulator.RecordCost with a synthetic provider name (no MCP envelope spoofing). |
|
openai
Package openai implements agent.ChatModel against the OpenAI Chat Completions API.
|
Package openai implements agent.ChatModel against the OpenAI Chat Completions API. |
|
Package orchestrator is the gridctl single-writer multi-agent primitive.
|
Package orchestrator is the gridctl single-writer multi-agent primitive. |
|
Package persist is the JSONL run-state ledger for the gridctl agent runtime.
|
Package persist is the JSONL run-state ledger for the gridctl agent runtime. |
|
Package runner orchestrates skill-run execution against the daemon's wired runtime, persisting the typed event ledger as it goes.
|
Package runner orchestrates skill-run execution against the daemon's wired runtime, persisting the typed event ledger as it goes. |
|
Package runtime aggregates the agent runtime's process-wide state into a single handle the gateway hangs off via SetAgentRuntime.
|
Package runtime aggregates the agent runtime's process-wide state into a single handle the gateway hangs off via SetAgentRuntime. |
|
Package sandbox runs typed TypeScript skills in goja with the gridctl-shaped agent bindings (tool, llm, parallel, handoff, approval) injected as globals.
|
Package sandbox runs typed TypeScript skills in goja with the gridctl-shaped agent bindings (tool, llm, parallel, handoff, approval) injected as globals. |
|
Package skill is the gridctl typed Skill SDK.
|
Package skill is the gridctl typed Skill SDK. |