Documentation
¶
Index ¶
- Constants
- func FormatToolResult(out any) (string, error)
- func MarshalOutboundData(v any) json.RawMessage
- type AfterToolHook
- type Agent
- type AgentID
- type Approval
- type ApprovalDecision
- type ApprovalRequest
- type AssistantMessageEvent
- type AssistantMessageEventType
- type BeforeStep
- type BeforeStepHook
- type BeforeToolHook
- type BudgetState
- type Command
- type CommandCollector
- type CommandProvider
- type CommandResult
- type Commands
- type ContentPart
- type Decision
- type DecisionKind
- type EventID
- type EventSeq
- type EventType
- type FollowUpMode
- type Hook
- type HookProvider
- type HookRuntime
- type JSONSchema
- type LLMEvent
- type LLMProvider
- type LLMRequest
- type LLMStream
- type Loop
- type LoopRequest
- type MessageEndPayload
- type MessageEvent
- type MessageStartPayload
- type MessageUpdatePayload
- type ModelMessage
- type OutboundEmit
- type OutboundEvent
- type Platform
- type PlatformIdentifier
- type Policy
- type PolicyInput
- type PromptAssembler
- type PromptRequest
- type PromptSection
- type Runner
- type Section
- type SectionProvider
- type Session
- type SessionEvent
- type SessionID
- type SessionStore
- type Tool
- type ToolBuilder
- type ToolCall
- type ToolCallID
- type ToolPack
- type ToolProvider
- type ToolResult
- type ToolRuntime
- type ToolSpec
- type TurnInput
- type TurnStopReason
- type TurnStopping
- type TurnStoppingHook
- type Usage
Constants ¶
const ( // KeySessionID is the context key for the current opaque SessionID. KeySessionID contextKey = "agentkit.session_id" // KeyAgentID is the context key for the current AgentID. KeyAgentID contextKey = "agentkit.agent_id" // KeyPlatformID is the context key for the current inbound/outbound platform. KeyPlatformID contextKey = "agentkit.platform_id" // KeyUserID is the context key for the current end-user identity, when known. KeyUserID contextKey = "agentkit.user_id" // KeyTurnID is the context key for the current turn, when one is active. KeyTurnID contextKey = "agentkit.turn_id" // KeyToolCallID is the context key for the current tool call, when one is active. KeyToolCallID contextKey = "agentkit.tool_call_id" // KeySessionControl is the context key for per-session steer/follow-up state. // Loop sets it before Agent.RunTurn; the value is a runtime/loop.Control that // also implements permission.Broker. KeySessionControl contextKey = "agentkit.session_control" // KeyOutboundEmit is the per-turn outbound hook. Loop sets it before // Agent.RunTurn so tools and permission waits can emit outbound events // through the same channel as assistant streaming. KeyOutboundEmit contextKey = "agentkit.outbound_emit" // KeyDeliverySessionID is the inbound delivery SessionID for the current turn // (finest grain). Outbound routing should prefer this over KeySessionID when // both are present. KeyDeliverySessionID contextKey = "agentkit.delivery_session_id" )
Variables ¶
This section is empty.
Functions ¶
func FormatToolResult ¶ added in v0.1.2
FormatToolResult converts a typed tool handler result into model-visible text.
func MarshalOutboundData ¶
func MarshalOutboundData(v any) json.RawMessage
Types ¶
type AfterToolHook ¶
type AfterToolHook interface {
Hook
AfterTool(context.Context, *ToolResult) error
}
func OnAfterTool ¶
func OnAfterTool(fn func(context.Context, *ToolResult) error) AfterToolHook
OnAfterTool wraps a function as an AfterToolHook.
type Agent ¶
Agent is the execution unit below Loop. It owns prompt, model, tools, policies and hooks for a single agent identity. Conversation state lives in Session; the agent implementation resolves Session via SessionStore using ctx.Value(KeySessionID). Loop does not inject Session objects or duplicate routing fields in TurnInput.
Steer/follow-up/cancel are owned by Loop per SessionID. Loop seeds ctx.Value(KeySessionControl) before RunTurn; Agent reads it for step-level steer interrupts.
Agent plugins declare SessionStore in their Deps struct (pluginkit injection).
type Approval ¶
type Approval interface {
Ask(context.Context, ApprovalRequest) (ApprovalDecision, error)
}
type ApprovalDecision ¶
type ApprovalRequest ¶
type AssistantMessageEvent ¶
type AssistantMessageEvent struct {
Type AssistantMessageEventType `json:"type"`
ContentIndex int `json:"contentIndex,omitempty"`
Delta string `json:"delta,omitempty"`
Content string `json:"content,omitempty"`
ID string `json:"id,omitempty"`
ToolName string `json:"toolName,omitempty"`
ToolCall *ToolCall `json:"toolCall,omitempty"`
Reason string `json:"reason,omitempty"`
ErrorMessage string `json:"errorMessage,omitempty"`
}
AssistantMessageEvent is the wire-safe Pi RPC delta payload (no cumulative partial).
type AssistantMessageEventType ¶
type AssistantMessageEventType string
AssistantMessageEventType mirrors Pi RPC assistantMessageEvent.type values.
const ( AssistantEventStart AssistantMessageEventType = "start" AssistantEventTextStart AssistantMessageEventType = "text_start" AssistantEventTextDelta AssistantMessageEventType = "text_delta" AssistantEventTextEnd AssistantMessageEventType = "text_end" AssistantEventThinkingStart AssistantMessageEventType = "thinking_start" AssistantEventThinkingDelta AssistantMessageEventType = "thinking_delta" AssistantEventThinkingEnd AssistantMessageEventType = "thinking_end" AssistantEventToolCallStart AssistantMessageEventType = "toolcall_start" AssistantEventToolCallDelta AssistantMessageEventType = "toolcall_delta" AssistantEventToolCallEnd AssistantMessageEventType = "toolcall_end" AssistantEventDone AssistantMessageEventType = "done" AssistantEventError AssistantMessageEventType = "error" )
const LLMEventMessage AssistantMessageEventType = "message"
LLMEventMessage carries a finalized (or snapshot) ModelMessage rather than a delta. It is internal to the provider/agent boundary and is never forwarded to platforms, so it has no counterpart in the Pi RPC event set.
type BeforeStep ¶
type BeforeStep struct {
Messages []ModelMessage
}
BeforeStep is invoked before a model step. Hooks read routing context from ctx.Value(KeySessionID) / ctx.Value(KeyAgentID); hooks that need durable state should depend on SessionStore via pluginkit Deps.
type BeforeStepHook ¶
type BeforeStepHook interface {
Hook
BeforeStep(context.Context, *BeforeStep) error
}
func OnBeforeStep ¶
func OnBeforeStep(fn func(context.Context, *BeforeStep) error) BeforeStepHook
OnBeforeStep wraps a function as a BeforeStepHook.
type BeforeToolHook ¶
func OnBeforeTool ¶
func OnBeforeTool(fn func(context.Context, *ToolCall) error) BeforeToolHook
OnBeforeTool wraps a function as a BeforeToolHook.
type BudgetState ¶
type BudgetState struct {
RemainingSteps int
RemainingContinuations int
RemainingSeconds int
RemainingTokens int
// SoftExhausted is true once any limited dimension crosses softRatio.
SoftExhausted bool
// Exhausted is true when a hard limit is reached; Continue is then ignored.
Exhausted bool
}
BudgetState reports what is left of the run budget. Unlimited dimensions report -1 so hooks can distinguish "no limit" from "nothing left".
type Command ¶
type Command interface {
Name() string
Alias() string
Description() string
CommandExec(ctx context.Context, args ...string) (string, error)
}
Command is one slash command contribution.
type CommandCollector ¶
type CommandCollector interface {
SetCommands(providers []CommandProvider) error
}
CommandCollector receives CommandProvider contributions after pluginkit build. Runner wires them with build.WireContributions during Run.
type CommandProvider ¶
type CommandProvider interface {
Commands() []Command
}
CommandProvider contributes human-facing commands from a built plugin instance. It is designed to work with pluginkit/build.WireContributions so commands can live next to the capability that owns their behavior.
type CommandResult ¶
CommandResult is the outcome of a handled slash command.
type Commands ¶
type Commands interface {
Dispatch(ctx context.Context, name string, args []string) (*CommandResult, error)
List() []Command
}
Commands is a post-build slash command catalog for platforms.
type ContentPart ¶
type Decision ¶
type Decision struct {
Kind DecisionKind
Reason string
// Audit is merged into ToolResult.Audit when the tool runtime denies a call.
Audit map[string]string
}
type DecisionKind ¶
type DecisionKind string
const ( DecisionAllow DecisionKind = "allow" DecisionDeny DecisionKind = "deny" DecisionAsk DecisionKind = "ask" )
type EventType ¶
type EventType string
const ( EventTurnStart EventType = "turn/start" EventTurnEnd EventType = "turn/end" EventStepStart EventType = "step/start" EventStepEnd EventType = "step/end" EventUserMessage EventType = "user/message" EventMessageStart EventType = "message/start" EventMessageUpdate EventType = "message/update" EventMessageEnd EventType = "message/end" EventAssistantMessage EventType = "assistant/message" EventToolCall EventType = "tool/call" EventToolResult EventType = "tool/result" EventCompaction EventType = "session/compaction" EventSkillLoad EventType = "skill/load" EventAutoRetryStart EventType = "retry/start" EventAutoRetryEnd EventType = "retry/end" EventSummarizationRetryStart EventType = "summarization/retry/start" EventSummarizationRetryEnd EventType = "summarization/retry/end" EventOverflowRecovery EventType = "overflow/recovery" EventTurnContinue EventType = "turn/continue" EventUsage EventType = "usage" EventTodoUpdate EventType = "todo/update" EventRunFinish EventType = "run/finish" EventSessionRecovery EventType = "session/recovery" EventSubagentStart EventType = "subagent/start" EventSubagentEnd EventType = "subagent/end" EventPermissionRequest EventType = "permission/request" EventPermissionResolved EventType = "permission/resolved" )
type FollowUpMode ¶
type FollowUpMode string
FollowUpMode controls how queued follow-up messages are drained after a turn.
const ( FollowUpOneAtATime FollowUpMode = "one-at-a-time" FollowUpAll FollowUpMode = "all" )
type Hook ¶
type Hook interface {
// contains filtered or unexported methods
}
Hook marks a value that may implement one or more hook point interfaces. Execution order follows deps.providers list order; within a provider, Hooks() slice order is preserved.
type HookProvider ¶
type HookProvider interface {
Hooks() []Hook
}
type HookRuntime ¶
type JSONSchema ¶
type JSONSchema struct {
Type string `json:"type,omitempty"`
Description string `json:"description,omitempty"`
Properties map[string]JSONSchema `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
Items *JSONSchema `json:"items,omitempty"`
Raw map[string]any `json:"-"`
}
func (JSONSchema) MarshalJSON ¶
func (s JSONSchema) MarshalJSON() ([]byte, error)
MarshalJSON emits Raw when set so MCP and other external schemas round-trip intact.
func (*JSONSchema) UnmarshalJSON ¶
func (s *JSONSchema) UnmarshalJSON(data []byte) error
UnmarshalJSON stores the full object in Raw and also fills known fields when present.
type LLMEvent ¶
type LLMEvent struct {
Type AssistantMessageEventType
Message *ModelMessage
ContentIndex int
Delta string
ToolCall *ToolCall
Usage *Usage
}
LLMEvent reuses AssistantMessageEventType so provider output and the platform-facing stream share one vocabulary. Providers emit the text_*, thinking_* and toolcall_* values plus LLMEventMessage; AssistantEventDone and AssistantEventError are wire-only and never produced here.
type LLMProvider ¶
LLMProvider streams model responses for an already assembled request. LLMRequest carries model-visible messages only; session routing is handled by the agent runtime before and after the provider boundary.
type LLMRequest ¶
type LLMRequest struct {
Model string
Messages []ModelMessage
Tools []ToolSpec
}
type Loop ¶
type Loop interface {
Dispatch(context.Context, LoopRequest) error
Steer(context.Context, ModelMessage) error
FollowUp(context.Context, ModelMessage) error
// TryDeliverPermission consumes a typed permission reply. It returns true
// when the message was handled and must not start a new turn.
TryDeliverPermission(MessageEvent) bool
// SupersedePendingForInbound cancels an active permission wait when a new
// user message arrives without a permission reply.
SupersedePendingForInbound(MessageEvent)
}
Loop is the turn scheduler. It routes inbound MessageEvents to agents, serializes work per SessionID, and owns per-session steer/follow-up control. Loop seeds ctx with KeySessionID/KeyDeliverySessionID/KeyAgentID/KeyPlatformID/KeyUserID/ KeySessionControl/KeyOutboundEmit before calling the agent. It does not resolve Session objects; that is the agent's responsibility.
type LoopRequest ¶
type LoopRequest struct {
Event MessageEvent
DeliverySessionID SessionID // platform delivery target; empty means Event.SessionID
Emit OutboundEmit
Capability any // permission.Capability, resolved by runner from the inbound platform
}
LoopRequest wraps one inbound message. Runner rewrites Event.SessionID to the effective id (after sessionScope) before Dispatch; DeliverySessionID keeps the platform routing target for outbound Send.
type MessageEndPayload ¶
type MessageEndPayload struct {
Message ModelMessage `json:"message"`
}
MessageEndPayload is emitted when an assistant message is finalized.
type MessageEvent ¶
type MessageEvent struct {
SessionID SessionID // required: platform delivery id
AgentID AgentID
PlatformID string
UserID string
Message ModelMessage
// Reply carries a permission answer as JSON. Decode with permission.DecodeReply.
Reply json.RawMessage `json:"reply,omitempty"`
}
MessageEvent is the inbound envelope from Platform to Loop. SessionID is the delivery target (finest grain); runner collapses it per sessionScope before Loop dispatch.
type MessageStartPayload ¶
type MessageStartPayload struct {
Message ModelMessage `json:"message"`
}
MessageStartPayload is emitted when assistant streaming begins.
type MessageUpdatePayload ¶
type MessageUpdatePayload struct {
Usage *Usage `json:"usage,omitempty"`
AssistantMessageEvent AssistantMessageEvent `json:"assistantMessageEvent"`
}
MessageUpdatePayload matches Pi RPC message_update events.
type ModelMessage ¶
type ModelMessage struct {
Role string
Content []ContentPart
ToolCalls []ToolCall
ToolResults []ToolResult
}
ModelMessage is model-visible content only. Session routing lives on event envelopes and context keys, not on ModelMessage.
type OutboundEmit ¶
type OutboundEmit func(context.Context, OutboundEvent) error
OutboundEmit sends platform events during a turn. When nil, streaming is suppressed.
type OutboundEvent ¶
type OutboundEvent struct {
SessionID SessionID // required
AgentID AgentID
PlatformID string
UserID string
Type EventType
Data json.RawMessage
}
OutboundEvent is the outbound envelope from Agent/Loop to Platform. SessionID must match the conversation that produced the turn so the platform can route the reply to the correct IM target.
type Platform ¶
type Platform interface {
Receive(context.Context) (MessageEvent, error)
Send(context.Context, OutboundEvent) error
}
Platform adapts external transports into AgentKit message events. Every inbound MessageEvent must carry a delivery SessionID (finest grain); runner applies sessionScope for scheduling and history. OutboundEvent.SessionID must be the delivery id so replies reach the correct IM target.
Concurrency contract:
- Receive is called from a single goroutine and may block.
- Send must be safe for concurrent use. Runner runs turns from different effective sessions in parallel (runner.config.maxConcurrentTurns, default 64); each turn emits from its own goroutine.
type PlatformIdentifier ¶ added in v0.1.1
type PlatformIdentifier interface {
PlatformID() string
}
PlatformIdentifier exposes the stable routing ID for a leaf platform. Multiplex and other aggregators use it to key sub-platforms without extra config; conflicts are disambiguated with an index suffix.
type Policy ¶
type Policy interface {
Evaluate(context.Context, PolicyInput) (Decision, error)
}
func PolicyFunc ¶
func PolicyFunc(fn func(context.Context, PolicyInput) Decision) Policy
PolicyFunc wraps a function as a Policy implementation.
type PolicyInput ¶
type PolicyInput struct {
ToolCall *ToolCall
}
PolicyInput carries the policy payload. Per-conversation policy should read ctx.Value(KeySessionID) / ctx.Value(KeyAgentID) / ctx.Value(KeyUserID).
type PromptAssembler ¶
type PromptAssembler interface {
Assemble(context.Context, PromptRequest) ([]ModelMessage, error)
}
PromptAssembler builds the model request prompt from registered sections.
type PromptRequest ¶
type PromptRequest struct {
Messages []ModelMessage
}
PromptRequest carries model-visible prompt inputs. Routing context is read from ctx.Value(KeySessionID) / ctx.Value(KeyAgentID) / ctx.Value(KeyUserID), not duplicated here.
type PromptSection ¶
PromptSection is one section provider contribution before it is folded into the leading system message.
type Runner ¶
type Runner interface {
// Run starts the process. result is the build graph produced alongside this
// runner; implementations may wire CommandProvider contributions to
// commands/registry before serving traffic.
Run(context.Context, *build.Result) error
Stop(context.Context) error
}
Runner is the root plugin type. It owns process lifecycle and connects a Platform to a Loop.
type Section ¶
type Section struct {
Name string
Build func(context.Context, PromptRequest) (PromptSection, error)
}
type SectionProvider ¶
type SectionProvider interface {
Sections() []Section
}
type Session ¶
type Session interface {
ID() SessionID
Append(context.Context, SessionEvent) (EventSeq, error)
Read(context.Context, EventSeq) ([]SessionEvent, error)
DeriveMessages(context.Context) ([]ModelMessage, error)
}
Session is the durable source of truth for model-visible state.
type SessionEvent ¶
type SessionEvent struct {
ID EventID
Seq EventSeq
SessionID SessionID
AgentID AgentID
Type EventType
Data json.RawMessage
CreatedAt time.Time
// UserID attributes the event to an end user. It is set on user messages
// when the platform knows who spoke, and is what makes a session shared by a
// whole Slack channel legible: without it the model reads one undifferentiated
// stream of user turns. Empty for single-user transports such as the CLI, and
// for everything the agent itself produces.
UserID string
}
type SessionID ¶
type SessionID string
SessionID identifies a conversation unit. Platforms emit a delivery SessionID (finest grain: channel + optional :t:thread + optional :u:user). Runner applies sessionScope to derive the effective SessionID used for Loop locking and session history; outbound replies still use the delivery id.
Delivery examples:
slack:C123ABC slack:C123ABC:t:1712345678.123456:u:U456 feishu:oc_xxx:om_yyy cli:default
Loop and Agent treat the effective SessionID as opaque. Only platform plugins decode delivery SessionIDs into IM routing targets.
type SessionStore ¶
SessionStore resolves durable sessions by opaque SessionID. Platform plugins generate SessionID values (cc-connect style: platform:segment:...); agent plugins depend on SessionStore and call Get with ctx.Value(KeySessionID) during RunTurn. Loop only uses SessionID for routing and per-session locking, never SessionStore.Get.
type Tool ¶
type Tool interface {
Name() string
Description() string
InputSchema() JSONSchema
Call(context.Context, json.RawMessage) (string, error)
}
Tool is the model-visible consumer plugin type.
Call receives only the raw arguments and returns model-visible text. The tool runtime stamps call identity onto a ToolResult before writing to session or sending back to the model.
type ToolBuilder ¶
type ToolBuilder[In, Out any] struct { // contains filtered or unexported fields }
func NewTool ¶
func NewTool[In, Out any](name string, handler func(context.Context, In) (Out, error)) *ToolBuilder[In, Out]
NewTool starts building a typed tool plugin. The input schema is inferred from In; any inference error surfaces from Build. Handler output is adapted to model-visible text: string is returned as-is, other values are JSON.
func (*ToolBuilder[In, Out]) Build ¶
func (b *ToolBuilder[In, Out]) Build() (Tool, error)
func (*ToolBuilder[In, Out]) Description ¶
func (b *ToolBuilder[In, Out]) Description(desc string) *ToolBuilder[In, Out]
func (*ToolBuilder[In, Out]) Schema ¶
func (b *ToolBuilder[In, Out]) Schema(schema JSONSchema) *ToolBuilder[In, Out]
Schema replaces the inferred input schema, discarding any inference error.
type ToolCall ¶
type ToolCall struct {
ID ToolCallID
Name string
Input json.RawMessage
}
type ToolCallID ¶
type ToolCallID string
type ToolPack ¶
type ToolPack []Tool
ToolPack is one plugin instance that exposes one or more model-visible tools.
type ToolProvider ¶
ToolProvider supplies tools whose definitions may change between turns. Implementations re-read configuration or rediscover remote tools on each call.
type ToolResult ¶
type ToolResult struct {
ID ToolCallID
Name string
Content string
Audit map[string]string
}
ToolResult is a tool output bound to a specific call, used by session history, hooks, and LLM wire-up. Audit is populated by the tool runtime (policy deny, timeout, etc.), not by Tool.Call.
func ResultFromCall ¶ added in v0.1.2
func ResultFromCall(call ToolCall, output string) ToolResult
ResultFromCall attaches call identity to a tool output.
type ToolRuntime ¶
type ToolSpec ¶
type ToolSpec struct {
Name string
Description string
InputSchema JSONSchema
}
type TurnInput ¶
type TurnInput struct {
Message ModelMessage
Emit OutboundEmit
}
TurnInput carries one turn's payload. Routing context is available through ctx.Value(KeySessionID), ctx.Value(KeyAgentID), ctx.Value(KeyUserID), and related agentkit keys.
type TurnStopReason ¶
type TurnStopReason string
TurnStopReason explains why the agent reached the end of a turn segment.
const ( // StopNoToolCalls means the assistant answered without requesting tools. StopNoToolCalls TurnStopReason = "no-tool-calls" // StopStepLimit means the per-segment step allowance ran out. StopStepLimit TurnStopReason = "step-limit" // StopBudget means a hard run budget is exhausted; Continue is ignored. StopBudget TurnStopReason = "budget" )
type TurnStopping ¶
type TurnStopping struct {
Reason TurnStopReason
Steps int
Segments int
Budget BudgetState
// Messages is the derived history at the stopping point. Read-only for hooks.
Messages []ModelMessage
// Continue holds messages that extend the turn. Hooks append to it.
Continue []ModelMessage
Stop bool
StopReason string
}
TurnStopping is invoked when the agent is about to end a turn. Hooks may append Continue messages to extend the turn with another segment, or set Stop to force the turn to end. Stop wins over Continue, and the agent ignores Continue when Budget.Exhausted is true: no hook can outrun a hard budget.
type TurnStoppingHook ¶
type TurnStoppingHook interface {
Hook
TurnStopping(context.Context, *TurnStopping) error
}
func OnTurnStopping ¶
func OnTurnStopping(fn func(context.Context, *TurnStopping) error) TurnStoppingHook
OnTurnStopping wraps a function as a TurnStoppingHook.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cap
|
|
|
filesystem
Package filesystem holds shared request/result types and gitignore helpers used by file tools.
|
Package filesystem holds shared request/result types and gitignore helpers used by file tools. |
|
permission
Package permission is the capability boundary for human-in-the-loop decisions routed through the inbound platform (tool approval, ask_user, etc.).
|
Package permission is the capability boundary for human-in-the-loop decisions routed through the inbound platform (tool approval, ask_user, etc.). |
|
schedule
Package schedule defines the calendar-scheduling capability: a durable set of cron jobs that schedule/cron fires and a tool can edit.
|
Package schedule defines the calendar-scheduling capability: a durable set of cron jobs that schedule/cron fires and a tool can edit. |
|
subagent
Package subagent defines the delegation capability: running a scoped child agent and bringing back only its conclusion.
|
Package subagent defines the delegation capability: running a scoped child agent and bringing back only its conclusion. |
|
tenant
Package tenant derives the isolation unit a conversation belongs to.
|
Package tenant derives the isolation unit a conversation belongs to. |
|
cmd
|
|
|
agent
command
|
|
|
runtime
|
|
|
helpdoc
Package helpdoc resolves pluginkit kind documentation for slash commands.
|
Package helpdoc resolves pluginkit kind documentation for slash commands. |
|
platform/headless
Package headless holds the platforms that run without an interactive terminal: platform/worker for one-shot batches and platform/timer for in-process schedules.
|
Package headless holds the platforms that run without an interactive terminal: platform/worker for one-shot batches and platform/timer for in-process schedules. |
|
subagent
Package subagent runs child agents in-process.
|
Package subagent runs child agents in-process. |
|
scripts
|
|
|
gen-imports
command
|