agent

package
v0.27.0 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: Apache-2.0, MIT Imports: 13 Imported by: 0

Documentation

Overview

Package agent provides a client for the Longbridge AI Agent conversation OpenAPI. It covers listing Workspaces and Agents, starting and continuing conversations, and streaming run progress over SSE.

Reference: https://open.longbridge.com/en/docs/ai/chat/conversation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Agent

type Agent struct {
	// UID is the Agent UID, used as the path parameter of
	// AgentContext.Conversation.
	UID string `json:"uid"`
	// Name is the Agent name.
	Name string `json:"name"`
	// Description is the Agent description.
	Description string `json:"description"`
	// Mode is the Agent mode, e.g. "chat".
	Mode string `json:"mode"`
	// Icon is the icon URL.
	Icon string `json:"icon"`
	// IsPublished reports whether the Agent is published; only published
	// Agents can start conversations.
	IsPublished bool `json:"is_published"`
	// PublishedAt is the publish time, Unix timestamp in seconds; 0 if
	// unpublished.
	PublishedAt int64 `json:"published_at"`
	// CreatedAt is the creation time, Unix timestamp in seconds.
	CreatedAt int64 `json:"created_at"`
	// UpdatedAt is the last updated time, Unix timestamp in seconds.
	UpdatedAt int64 `json:"updated_at"`
}

Agent is an Agent in a Workspace.

type AgentContext

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

AgentContext is a client for the Longbridge AI Agent conversation OpenAPI.

Example:

conf, err := config.NewFromEnv()
actx, err := agent.NewFromCfg(conf)
resp, err := actx.Conversation(context.Background(), "ag_7d3f9b2c", "How has Tesla stock performed recently?", "", "")

func NewFromCfg

func NewFromCfg(cfg *config.Config) (*AgentContext, error)

NewFromCfg creates an AgentContext from a *config.Config.

Both blocking and streamed conversation calls can legitimately run far longer than a typical REST call (a full LLM turn), so unless cfg.Client is already set, AgentContext uses its own underlying *http.Client with no overall timeout: blocking calls (Conversation, Continue) are instead bounded by a dedicated per-request timeout (see requestTimeout), and streamed calls (ConversationStream, ContinueStream) are left unbounded — only ctx cancellation stops them.

func NewFromEnv

func NewFromEnv() (*AgentContext, error)

NewFromEnv returns an AgentContext configured from environment variables.

func (*AgentContext) Agents

func (c *AgentContext) Agents(ctx context.Context, workspaceID string, opts *GetAgentsOptions) (*AgentsResponse, error)

Agents lists the Agents in the specified Workspace. opts is optional; pass nil to use the server defaults (page 1, limit 20, no name filter).

The returned Agent.UID is the identifier used by Conversation; only Agents with IsPublished set can start conversations.

Path: GET /v1/ai/workspaces/{id}/agents

func (*AgentContext) Continue

func (c *AgentContext) Continue(ctx context.Context, agentID, chatUID, messageID string, answers AnswersByToolCall) (*ConversationResponse, error)

Continue resumes an interrupted conversation (a Conversation or Continue call that returned Status ConversationStatusInterrupted), blocking until the run succeeds, is interrupted again, or fails.

chatUID and messageID come from the interrupted response: chatUID is its ChatUID, and messageID is its Interrupt.MessageID (as a string). answers is keyed by Interrupt.ToolCallID; see AnswersByToolCall's docs for its shape. Every question the interrupt asked must be answered.

A single round of conversation may be interrupted multiple times: if the run returns ConversationStatusInterrupted again after continuing, call Continue again with the new Interrupt.

Path: POST /v1/ai/agents/{id}/conversations/{chat_uid}/messages/{message_id}/continue

func (*AgentContext) ContinueStream

func (c *AgentContext) ContinueStream(ctx context.Context, agentID, chatUID, messageID string, answers AnswersByToolCall) (*ConversationStream, error)

ContinueStream resumes an interrupted conversation, returning a *ConversationStream of run-progress events delivered over SSE as they arrive, instead of blocking for the final result the way Continue does. See ConversationStream's docs for how to drain it correctly. The caller must Close the returned stream once done with it.

Path: POST /v1/ai/agents/{id}/conversations/{chat_uid}/messages/{message_id}/continue (Accept: text/event-stream)

func (*AgentContext) Conversation

func (c *AgentContext) Conversation(ctx context.Context, agentID, query, chatUID, parentMessageID string) (*ConversationResponse, error)

Conversation asks a question to the specified Agent, blocking until the run succeeds, is interrupted, or fails.

chatUID identifies an existing conversation to continue asking in; pass an empty string to start a new one.

parentMessageID attaches this message after a specific earlier message in an existing conversation, keeping the message stream in order; take it from the MessageID of a previous response. It is only valid together with a non-empty chatUID, the parent message must belong to that conversation, and it must be left empty when starting a new conversation.

The Agent generates the answer using capabilities such as market data and account access. When the Agent needs more information or confirmation from you, the run is interrupted (Status is ConversationStatusInterrupted) — send your answers via Continue to resume it.

Path: POST /v1/ai/agents/{id}/conversations

func (*AgentContext) ConversationStream

func (c *AgentContext) ConversationStream(ctx context.Context, agentID, query, chatUID, parentMessageID string) (*ConversationStream, error)

ConversationStream starts a conversation with the specified Agent, returning a *ConversationStream of run-progress events delivered over SSE as they arrive, instead of blocking for the final result the way Conversation does.

A ConversationStreamEvent of type *WorkflowFinishedEvent carries the run's outcome, but it isn't necessarily the last event — the server may still emit a few more housekeeping events (e.g. a *ChatTitleUpdatedEvent) before closing the connection, so keep calling Next until it returns false rather than stopping as soon as you see it. The caller must Close the returned stream once done with it.

An interrupted run does not emit a *WorkflowFinishedEvent at all: it emits a *HumanInteractionRequiredEvent instead, followed directly by *ChatFinishedEvent — send answers via ContinueStream (or Continue) using its Interrupt details to resume.

chatUID identifies an existing conversation to continue asking in; pass an empty string to start a new one.

parentMessageID attaches this message after a specific earlier message in an existing conversation; see Conversation for its constraints.

Path: POST /v1/ai/agents/{id}/conversations (Accept: text/event-stream)

func (*AgentContext) PublicAgents

func (c *AgentContext) PublicAgents(ctx context.Context, opts *GetAgentsOptions) (*AgentsResponse, error)

PublicAgents lists all publicly available Agents on the platform (the Explore catalog). Unlike Agents, it is not scoped to a Workspace and returns every published, publicly-shared Agent. opts is optional; pass nil to use the server defaults (page 1, limit 20, no name filter).

The returned Agent.UID is the identifier used by Conversation; only Agents with IsPublished set can start conversations.

Path: GET /v1/ai/agents

func (*AgentContext) Workspaces

func (c *AgentContext) Workspaces(ctx context.Context) (*WorkspacesResponse, error)

Workspaces lists the Workspaces the current account belongs to. A Workspace is the organizational unit for Agents: find the target Workspace here first, then use Agents to list the Agents available in it.

Path: GET /v1/ai/workspaces

type AgentsResponse

type AgentsResponse struct {
	// Agents is the Agent list.
	Agents []Agent `json:"agents"`
	// Total is the total number of matching Agents.
	Total int32 `json:"total"`
}

AgentsResponse is the response for AgentContext.Agents.

type AnswersByToolCall

type AnswersByToolCall map[string]map[string]string

AnswersByToolCall is answers keyed by Interrupt.ToolCallID, each value being a map of question text to answer, used as the request body of AgentContext.Continue and AgentContext.ContinueStream.

The outer key corresponds to Interrupt.ToolCallID. The inner key is the Question.Question text, and the value is the answer selected or typed for it. Every question the interrupt asked must be answered.

type ChatFinishedEvent

type ChatFinishedEvent struct {
	// ChatID is the ID of the owning conversation.
	ChatID int64 `json:"chat_id"`
	// ChatUID identifies the conversation.
	ChatUID string `json:"chat_uid"`
	// MessageID is the message ID of this round.
	MessageID string `json:"message_id"`
	// Error has been empty in every run observed so far.
	Error string `json:"error"`
	// ErrorMessage has been empty in every run observed so far.
	ErrorMessage string `json:"error_message"`
}

ChatFinishedEvent is observed once all MessageEvents for this round have been sent, shortly before WorkflowFinishedEvent.

func (*ChatFinishedEvent) UnmarshalJSON

func (e *ChatFinishedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts message_id as either a JSON string or a JSON number; see ChatStartedEvent.UnmarshalJSON.

type ChatStartedEvent

type ChatStartedEvent struct {
	// ChatUID identifies the conversation.
	ChatUID string `json:"chat_uid"`
	// MessageID is the message ID of this round.
	MessageID string `json:"message_id"`
	// ChatID is the ID of the owning conversation.
	ChatID int64 `json:"chat_id"`
	// Error is the error detail; empty at start.
	Error string `json:"error"`
	// ErrorMessage is the user-facing error message; empty at start.
	ErrorMessage string `json:"error_message"`
}

ChatStartedEvent reports that the run has started.

func (*ChatStartedEvent) UnmarshalJSON

func (e *ChatStartedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts message_id as either a JSON string or a JSON number: the docs' SSE example encodes it as a raw number here, unlike the blocking response's top-level message_id, which is a quoted string.

type ChatTitleUpdatedEvent

type ChatTitleUpdatedEvent struct {
	// ChatID is the ID of the owning conversation.
	ChatID int64 `json:"chat_id"`
	// ChatUID identifies the conversation.
	ChatUID string `json:"chat_uid"`
	// Source describes where the title came from, e.g. "ai_generated".
	Source string `json:"source"`
	// Title is the new (possibly truncated) title.
	Title string `json:"title"`
	// UpdatedAt is a Unix timestamp in seconds.
	UpdatedAt int64 `json:"updated_at"`
}

ChatTitleUpdatedEvent reports the server auto-generating a short title for the conversation, as a UI convenience. Can arrive before or after WorkflowFinishedEvent; not tied to the run's outcome.

type ConversationError

type ConversationError struct {
	// Code is the error code.
	Code int32 `json:"code"`
	// Message is the error message.
	Message string `json:"message"`
}

ConversationError is present when a conversation run failed.

type ConversationResponse

type ConversationResponse struct {
	// ChatUID identifies the conversation, used for follow-up questions and
	// troubleshooting.
	ChatUID string `json:"chat_uid"`
	// MessageID is the message ID of this round.
	MessageID string `json:"message_id"`
	// Status is the final run status.
	Status ConversationStatus `json:"status"`
	// Answer is the final answer text; valid when Status is
	// ConversationStatusSucceeded.
	Answer string `json:"answer"`
	// References are sources referenced by the answer; nil if none.
	References []Reference `json:"references"`
	// FurtherQuestions are suggested follow-up questions ("you might also
	// ask"); nil if none.
	FurtherQuestions []string `json:"further_questions"`
	// ElapsedTime is the run duration in seconds.
	ElapsedTime float64 `json:"elapsed_time"`
	// Interrupt is present only when Status is ConversationStatusInterrupted.
	Interrupt *Interrupt `json:"interrupt"`
	// Error is present only when the run failed.
	Error *ConversationError `json:"error"`
}

ConversationResponse is the response for AgentContext.Conversation and AgentContext.Continue, and the outcome carried by WorkflowFinishedEvent when streaming.

func (*ConversationResponse) UnmarshalJSON

func (r *ConversationResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts message_id as either a JSON string or a JSON number: the blocking response's top-level message_id is a quoted string, but callers building a ConversationResponse from streamed events may feed it the numeric form seen in some SSE payloads (see ChatStartedEvent).

type ConversationStatus

type ConversationStatus string

ConversationStatus is the final run status of a conversation.

const (
	// ConversationStatusSucceeded means the run completed successfully.
	ConversationStatusSucceeded ConversationStatus = "succeeded"
	// ConversationStatusInterrupted means the run is paused, waiting for
	// AgentContext.Continue.
	ConversationStatusInterrupted ConversationStatus = "interrupted"
	// ConversationStatusFailed means the run failed.
	ConversationStatusFailed ConversationStatus = "failed"
	// ConversationStatusStopped means the run was stopped.
	ConversationStatusStopped ConversationStatus = "stopped"
)

type ConversationStream

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

ConversationStream is an open server-sent-events stream of ConversationStreamEvent values from AgentContext.ConversationStream or AgentContext.ContinueStream.

Call Next repeatedly to advance through the stream; it returns false once the stream ends or an error occurs — call Err to tell the two apart. Call Close once done, whether or not the stream was drained to the end.

Usage:

stream, err := actx.ConversationStream(ctx, agentID, query, "", "")
if err != nil {
	// handle err
}
defer stream.Close()
for stream.Next() {
	switch e := stream.Event().(type) {
	case *agent.MessageEvent:
		fmt.Print(e.Text)
	case *agent.WorkflowFinishedEvent:
		result = e.ConversationResponse
	case *agent.HumanInteractionRequiredEvent:
		interrupt = e.Interrupt
	}
}
if err := stream.Err(); err != nil {
	// handle err
}

func (*ConversationStream) Close

func (s *ConversationStream) Close() error

Close closes the underlying connection. Safe to call more than once.

func (*ConversationStream) Err

func (s *ConversationStream) Err() error

Err returns the first error encountered while reading the stream, if any.

func (*ConversationStream) Event

Event returns the event Next just advanced to. Only valid after a call to Next that returned true.

func (*ConversationStream) Next

func (s *ConversationStream) Next() bool

Next advances the stream to the next event. It returns false once the stream ends or an error occurs; call Err to distinguish the two.

type ConversationStreamEvent

type ConversationStreamEvent interface {
	// contains filtered or unexported methods
}

ConversationStreamEvent is implemented by every event observed while draining a *ConversationStream. Use a type switch to handle it:

switch e := stream.Event().(type) {
case *agent.MessageEvent:
	fmt.Print(e.Text)
case *agent.WorkflowFinishedEvent:
	result = e.ConversationResponse
case *agent.HumanInteractionRequiredEvent:
	interrupt = e.Interrupt
}

type GetAgentsOptions

type GetAgentsOptions struct {
	// Page is the page number, starting at 1. 0 uses the server default.
	Page int32
	// Limit is the page size. 0 uses the server default.
	Limit int32
	// Name fuzzy-searches by Agent name. Empty omits the filter.
	Name string
}

GetAgentsOptions holds the optional query parameters for AgentContext.Agents. The zero value uses the server defaults (page 1, limit 20, no name filter).

type HumanInteraction

type HumanInteraction struct {
	// ToolCallID is the tool call that requested the interaction.
	ToolCallID string `json:"tool_call_id"`
	// InterruptID is the stable key expected by the answers map when continuing.
	InterruptID string `json:"interrupt_id"`
	// InteractionType is the interaction type such as "ask_human" or
	// "trade_password".
	InteractionType string `json:"type"`
	// ToolName is the human-readable tool name.
	ToolName string `json:"tool_name"`
	// Questions and answer options presented to the user.
	Questions []Question `json:"questions"`
	// ToolArgs is the original tool arguments, retained for host-specific UI
	// rendering.
	ToolArgs json.RawMessage `json:"tool_args"`
}

Interrupt is present when a conversation run is interrupted, waiting for AgentContext.Continue. HumanInteraction is a single interaction requested while an Agent workflow is paused.

type HumanInteractionRequiredEvent

type HumanInteractionRequiredEvent struct {
	*Interrupt
}

HumanInteractionRequiredEvent reports that the run is paused, waiting for more information from the caller — send answers via AgentContext.Continue or AgentContext.ContinueStream to resume it. An interrupted run does not emit WorkflowFinishedEvent; this event carries the interrupt details instead, and the stream ends with ChatFinishedEvent right after it.

type Interrupt

type Interrupt struct {
	// NodeID is the ID of the node that triggered the interrupt.
	NodeID string `json:"node_id"`
	// ToolCallID is the tool call ID of this inquiry; used as the outer key
	// of AnswersByToolCall when continuing.
	ToolCallID string `json:"tool_call_id"`
	// Questions you need to answer.
	Questions []Question `json:"questions"`
	// Interactions are the full interaction descriptors used to render and
	// answer the pause.
	Interactions []HumanInteraction `json:"interactions"`
	// MessageID is the ID of the paused message.
	MessageID int64 `json:"message_id"`
	// ChatID is the ID of the owning conversation.
	ChatID int64 `json:"chat_id"`
}

type MessageEvent

type MessageEvent struct {
	// Text is the incremental answer text.
	Text string `json:"text"`
}

MessageEvent is an incremental piece of the answer.

type OtherEvent

type OtherEvent struct {
	// Event is the SSE envelope's "event" field (the event type name).
	Event string
	// Data is the SSE envelope's "data" field.
	Data json.RawMessage
}

OtherEvent is an event type not recognized by this SDK version, carried as raw JSON so callers aren't broken by future additions to the API. Event is the SSE envelope's discriminator string, so callers can at least tell these apart instead of getting an opaque blob.

type PingEvent

type PingEvent struct{}

PingEvent is a heartbeat with no payload, observed at arbitrary points in the stream (including in between MessageEvent chunks).

type Question

type Question struct {
	// Question is the question text.
	Question string `json:"question"`
	// Options are the answer options; empty means free-form answer.
	Options []QuestionOption `json:"options"`
	// MultiSelect reports whether multiple options may be selected.
	MultiSelect bool `json:"multi_select"`
}

Question is one question the Agent needs you to answer to resume an interrupted conversation.

type QuestionOption

type QuestionOption struct {
	// Label is the short UI label for the option.
	Label string `json:"label"`
	// Description is the option text.
	Description string `json:"description"`
}

QuestionOption is one option of a Question.

type Reference

type Reference struct {
	// Index is the reference index.
	Index int32 `json:"index"`
	// OriginalIndex is the index in the source list before any reranking.
	OriginalIndex int32 `json:"original_index"`
	// RefType is the reference kind, e.g. "NewsArticle".
	RefType string `json:"type"`
	// ID is the reference id.
	ID string `json:"id"`
	// Title is the reference title. Often empty at the top level — the
	// human-readable title usually lives in Content.
	Title string `json:"title"`
	// URL is the reference URL. Often empty at the top level — see Content.
	URL string `json:"url"`
	// Content is the full reference payload as sent by the server (source,
	// description, published_at, source_url, source_logo, kind, …), kept as
	// raw JSON because the field set varies by RefType. nil if absent.
	Content json.RawMessage `json:"content"`
}

Reference is a source referenced by the answer.

type WorkflowFinishedEvent

type WorkflowFinishedEvent struct {
	*ConversationResponse
}

WorkflowFinishedEvent reports that the run finished (succeeded, failed, or stopped), carrying the run's outcome. Not emitted when the run is interrupted instead — see HumanInteractionRequiredEvent. Not necessarily the last event of the stream — the server may still emit a few more housekeeping events (e.g. ChatTitleUpdatedEvent) before actually closing the connection, so keep draining the stream until Next returns false rather than stopping as soon as this is seen.

type WorkflowStartedEvent

type WorkflowStartedEvent struct {
	// HitCache reports whether this run's answer was served from a cache.
	HitCache bool `json:"hit_cache"`
	// Inputs echoes the run's inputs.
	Inputs WorkflowStartedInputs `json:"inputs"`
	// StartedAt is a Unix timestamp in seconds.
	StartedAt int64 `json:"started_at"`
	// WorkflowID is an internal workflow run ID.
	WorkflowID int64 `json:"workflow_id"`
}

WorkflowStartedEvent is observed right after ChatStartedEvent on every run seen so far.

type WorkflowStartedInputs

type WorkflowStartedInputs struct {
	// ChatID is the ID of the owning conversation.
	ChatID int64 `json:"chat_id"`
	// ChatUID identifies the conversation.
	ChatUID string `json:"chat_uid"`
	// MessageID is the message ID of this round.
	MessageID string `json:"message_id"`
	// Query is the question that was asked.
	Query string `json:"query"`
}

WorkflowStartedInputs echoes the run's inputs, carried by WorkflowStartedEvent.

func (*WorkflowStartedInputs) UnmarshalJSON

func (i *WorkflowStartedInputs) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts message_id as either a JSON string or a JSON number; see ChatStartedEvent.UnmarshalJSON.

type Workspace

type Workspace struct {
	// ID is the Workspace ID.
	ID string `json:"id"`
	// Name is the Workspace name.
	Name string `json:"name"`
	// CreatedAt is the creation time, Unix timestamp in seconds.
	CreatedAt int64 `json:"created_at"`
	// UpdatedAt is the last updated time, Unix timestamp in seconds.
	UpdatedAt int64 `json:"updated_at"`
}

Workspace is a Workspace the current account belongs to.

type WorkspacesResponse

type WorkspacesResponse struct {
	// Workspaces the current account belongs to.
	Workspaces []Workspace `json:"workspaces"`
}

WorkspacesResponse is the response for AgentContext.Workspaces.

Jump to

Keyboard shortcuts

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