agui

package
v2.13.0 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package agui serves PromptKit conversations over the AG-UI protocol (1.0), using the AG-UI community Go SDK's types. It provides bidirectional converters between PromptKit and AG-UI messages and tools, and an EventAdapter that turns one conversation turn into one AG-UI run.

Not produced: token-by-token text streaming (each message's text arrives in one TEXT_MESSAGE_CONTENT), reasoning events, STATE_DELTA, MESSAGES_SNAPSHOT, and the pendingToolCallIds of a run that leaves frontend tool calls unanswered. Message ids are minted per conversion, so converting the same message twice gives two ids.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrContinueUnsupported = errors.New("agui: conversation does not support Continue")

ErrContinueUnsupported is returned by EventAdapter.RunContinue when the conversation cannot continue after an approval hold.

Functions

func MessageFromAGUI

func MessageFromAGUI(msg *aguitypes.Message) types.Message

MessageFromAGUI converts an AG-UI Message to a PromptKit Message. It maps roles, content (text or multimodal), tool calls, and tool call IDs.

A reasoning message becomes an assistant message whose Reasoning holds the text, never user input. MessagesFromAGUI folds it into the assistant message that follows it instead.

Example

ExampleMessageFromAGUI converts an AG-UI Message back to a PromptKit Message, the inverse of agui.MessageToAGUI.

package main

import (
	"fmt"

	aguitypes "github.com/ag-ui-protocol/ag-ui/sdks/community/go/pkg/core/types"

	"github.com/AltairaLabs/PromptKit/sdk/v2/agui"
)

func main() {
	aguiMsg := &aguitypes.Message{
		Role:    aguitypes.RoleAssistant,
		Content: "Hi there!",
	}
	msg := agui.MessageFromAGUI(aguiMsg)
	fmt.Println(msg.Role, "->", msg.GetContent())
}
Output:
assistant -> Hi there!

func MessageToAGUI

func MessageToAGUI(msg *types.Message) aguitypes.Message

MessageToAGUI converts a PromptKit Message to an AG-UI Message. It maps roles, content, tool calls, and tool results.

User and tool messages carry content parts (text, image, audio, video, document) when they hold media; assistant and system content is text, as AG-UI 1.0 defines it. A media part whose bytes are neither inline nor at a URL (a local file path or a storage reference) has no AG-UI form and is dropped with a warning.

Example

ExampleMessageToAGUI converts a PromptKit Message to the AG-UI wire format used by AG-UI-compatible frontends.

package main

import (
	"fmt"

	"github.com/AltairaLabs/PromptKit/runtime/v2/types"
	"github.com/AltairaLabs/PromptKit/sdk/v2/agui"
)

func main() {
	msg := types.NewTextMessage("user", "Hello!")
	aguiMsg := agui.MessageToAGUI(&msg)
	fmt.Println(aguiMsg.Role, "->", aguiMsg.Content)
}
Output:
user -> Hello!

func MessagesFromAGUI

func MessagesFromAGUI(msgs []aguitypes.Message) []types.Message

MessagesFromAGUI converts a slice of AG-UI Messages to PromptKit Messages.

A reasoning message is attached to the assistant message that follows it, as that message's Reasoning; with no assistant message after it, it is dropped. Activity messages are UI material that AG-UI says never travels back to the agent, and are dropped too.

func MessagesToAGUI

func MessagesToAGUI(msgs []types.Message) []aguitypes.Message

MessagesToAGUI converts a slice of PromptKit Messages to AG-UI Messages.

func ToolsFromAGUI

func ToolsFromAGUI(aguiTools []aguitypes.Tool) []*tools.ToolDescriptor

ToolsFromAGUI converts a slice of AG-UI Tool definitions to PromptKit ToolDescriptors. Each tool's Parameters (JSON Schema as any) is marshaled to json.RawMessage for InputSchema.

The tools in RunAgentInput.tools are the application's own, executed by the application, so each descriptor has Mode "client": a call to one suspends the turn until the application answers it.

func ToolsToAGUI

func ToolsToAGUI(descs []tools.ToolDescriptor) []aguitypes.Tool

ToolsToAGUI converts a slice of PromptKit ToolDescriptors to AG-UI Tool definitions.

Types

type AdapterOption

type AdapterOption func(*adapterConfig)

AdapterOption configures an EventAdapter.

func WithRunID

func WithRunID(id string) AdapterOption

WithRunID sets the AG-UI run ID for emitted events.

func WithStateProvider

func WithStateProvider(sp StateProvider) AdapterOption

WithStateProvider sets a provider that produces state snapshots.

func WithThreadID

func WithThreadID(id string) AdapterOption

WithThreadID sets the AG-UI thread ID for emitted events.

func WithToolResultProvider

func WithToolResultProvider(provider ToolResultProvider) AdapterOption

WithToolResultProvider sets a callback that answers pending client tools on the server, inside the run. When the callback answers every pending call, the adapter resolves them, emits a TOOL_CALL_RESULT for each, and resumes the turn. Calls it leaves unanswered stay pending: the run finishes with them unanswered, as AG-UI requires for a frontend tool, and the application answers them in the next run (see EventAdapter.RunResume).

Use it only for tools the server itself can answer. A frontend tool, one the application advertised in RunAgentInput.tools, must not be answered by the producer.

func WithWorkflowSteps

func WithWorkflowSteps(enabled bool) AdapterOption

WithWorkflowSteps enables STEP_STARTED / STEP_FINISHED events naming the workflow state a run executes in. It has an effect only when the conversation runs a workflow, as one passed to NewWorkflowEventAdapter does; NewWorkflowEventAdapter enables it by default.

type EventAdapter

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

EventAdapter bridges a PromptKit conversation to an AG-UI event channel. It runs one conversation turn and translates the turn's messages into AG-UI protocol events. An adapter carries one run: its channel closes when the run ends.

func NewEventAdapter

func NewEventAdapter(conv interface {
	Sender
	EventBusProvider
}, opts ...AdapterOption,
) *EventAdapter

NewEventAdapter creates a new EventAdapter for the given conversation. The conversation must implement both Sender and EventBusProvider. In practice, *sdk.Conversation satisfies both interfaces.

func NewWorkflowEventAdapter added in v2.11.0

func NewWorkflowEventAdapter(wc *sdk.WorkflowConversation, opts ...AdapterOption) *EventAdapter

NewWorkflowEventAdapter creates an EventAdapter for a workflow conversation. Each run opens a step named after the workflow state it executes in, and a transition the turn commits finishes that step and starts the next. Pass WithWorkflowSteps(false) to leave the steps out.

Client-tool results and approval resolutions go to the workflow's active conversation, the one serving the current state.

func (*EventAdapter) Events

func (a *EventAdapter) Events() <-chan aguievents.Event

Events returns the read-only channel of AG-UI events. The channel is closed when the run ends, successfully or with an error.

Drain it concurrently with RunSend, RunResume or RunContinue, for example from another goroutine. The adapter never drops an event. When the channel's buffer is full it waits for the reader, so a reader that stops reading holds the run until the run's context is canceled; cancel it (an HTTP handler's request context is canceled when the client disconnects) to release the run.

func (*EventAdapter) RunContinue added in v2.11.0

func (a *EventAdapter) RunContinue(ctx context.Context) error

RunContinue continues a turn whose approval-held tool calls were resolved (sdk.Conversation.ResolveTool / RejectTool) and emits it as a new run.

Read Events() concurrently with the run, or cancel ctx: the run waits for the reader once the channel's buffer of 64 events is full. A caller that lets the run finish before reading blocks there; adapters before this version dropped the events that did not fit instead.

The held calls' results are emitted as TOOL_CALL_RESULT events, since only the agent knows them.

It returns ErrContinueUnsupported (after a RUN_ERROR) when the conversation has no Continue method.

func (*EventAdapter) RunID

func (a *EventAdapter) RunID() string

RunID returns the run ID used by this adapter.

func (*EventAdapter) RunResume added in v2.11.0

func (a *EventAdapter) RunResume(ctx context.Context, results []ToolResult) error

RunResume answers the client tool calls a previous run left pending and emits the continued turn as a new run.

Read Events() concurrently with the run, or cancel ctx: the run waits for the reader once the channel's buffer of 64 events is full. A caller that lets the run finish before reading blocks there; adapters before this version dropped the events that did not fit instead.

In AG-UI the application answers a frontend tool call in the next run's input, as a tool message per call; ToolResultsFromAGUI extracts them. The answers are the application's own, so the run does not echo them back as TOOL_CALL_RESULT events. Nor does it repeat answers a ToolResultProvider gave in the earlier run, which reported them then: the resumed turn feeds every answer to the model, but none of them is new to the client.

func (*EventAdapter) RunSend

func (a *EventAdapter) RunSend(ctx context.Context, msg *types.Message) error

RunSend sends a message through the conversation and emits the run's AG-UI events.

Event sequence on success:

  1. RUN_STARTED
  2. STATE_SNAPSHOT (if a StateProvider is configured)
  3. STEP_STARTED for the current workflow state (workflow conversations)
  4. For each assistant message the turn produced, in order: TEXT_MESSAGE_START / TEXT_MESSAGE_CONTENT / TEXT_MESSAGE_END, then TOOL_CALL_START / TOOL_CALL_ARGS / TOOL_CALL_END for each call it made; each tool result the turn fed back to the model is a TOOL_CALL_RESULT
  5. STEP_FINISHED / STEP_STARTED when the turn moved the workflow on
  6. If a ToolResultProvider answers the pending client tools: a TOOL_CALL_RESULT for each, then the resumed turn from step 4
  7. STEP_FINISHED for the open step
  8. RUN_FINISHED

A client tool call left pending ends the run with the call unanswered; the application answers it in the next run with EventAdapter.RunResume. An approval-held call (sdk.Conversation.OnToolAsync) ends the run with RUN_FINISHED carrying an interrupt outcome that names the held calls; the next run continues with EventAdapter.RunContinue.

Text arrives as one TEXT_MESSAGE_CONTENT per message once the turn has run; it is not streamed token by token.

On error, a RUN_ERROR ends the run. The events channel is always closed when RunSend returns.

Read Events() concurrently with the run, or cancel ctx: the run waits for the reader once the channel's buffer of 64 events is full. A caller that lets the run finish before reading blocks there; adapters before this version dropped the events that did not fit instead.

func (*EventAdapter) ThreadID

func (a *EventAdapter) ThreadID() string

ThreadID returns the thread ID used by this adapter.

type EventBusProvider

type EventBusProvider interface {
	EventBus() events.Bus
}

EventBusProvider abstracts access to the conversation's event bus.

type Sender

type Sender interface {
	Send(ctx context.Context, message any, opts ...sdk.SendOption) (*sdk.Response, error)
	SendToolResult(ctx context.Context, callID string, result any) error
	RejectClientTool(ctx context.Context, callID, reason string)
	Resume(ctx context.Context) (*sdk.Response, error)
}

Sender abstracts the conversation methods needed by the adapter. In production code, *sdk.Conversation satisfies this interface.

type StateProvider

type StateProvider interface {
	Snapshot(sender Sender) (any, error)
}

StateProvider produces a state snapshot for the AG-UI StateSnapshotEvent.

type ToolResult

type ToolResult struct {
	CallID   string // must match PendingClientTool.CallID
	Result   any    // JSON-serializable, or []types.ContentPart; ignored when Rejected is true
	Rejected bool
	Reason   string // rejection reason (used when Rejected is true)
	// Error reports that the tool failed. Result, when also set, is the
	// partial output it produced before failing.
	Error string
}

ToolResult carries the caller-provided outcome for a single client tool call.

func ToolResultsFromAGUI added in v2.11.0

func ToolResultsFromAGUI(msgs []aguitypes.Message) []ToolResult

ToolResultsFromAGUI returns the answers a RunAgentInput carries for the client tool calls a previous run left pending: the tool messages at the end of msgs, after the last message of any other role. Pass them to EventAdapter.RunResume. It returns nil when msgs does not end with a tool message.

The trailing tool messages can include results the agent itself produced in that round (a server tool's TOOL_CALL_RESULT the application kept in its history). An sdk.Conversation resumes with an answer only for a call it has no result for yet, so passing them along is harmless.

A tool message's content becomes the Result: text that is a JSON document is passed through as JSON, other text as a string, and content parts as []types.ContentPart. Its error becomes Error.

type ToolResultProvider

type ToolResultProvider func(ctx context.Context, tools []sdk.PendingClientTool) ([]ToolResult, error)

ToolResultProvider is a callback the caller implements to supply results for pending client tools. The adapter calls it when the LLM response contains deferred client tools that need fulfillment before the pipeline can continue.

Jump to

Keyboard shortcuts

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