Documentation
¶
Overview ¶
Package live turns togo into an AI-agent bridge: push a prompt (a row in a table, a chat message, or a third-party message like WhatsApp) and a live agent — Claude/omni running in its own Coder workspace — answers it, with the reply streamed back over the same channel.
Two runtime modes, selected by LIVE_MODE, share one data model and API:
- agent-driven (default): a long-running claude/omni inside a Coder workspace polls its inbox and pushes replies through the live MCP bridge (cmd/live-mcp → token-guarded /api/live/inbox + /reply). "The agent reads the table over MCP and pushes responses."
- server-driven: an in-app runner claims pending prompts and invokes the agent one-shot via a Responder (echo/claude/slot), replaying the transcript for context. Zero always-on workspace; reuses the togo impl/exec slots (omnigent + coder) when selected.
Mounted under /api/live/*; a self-contained chat board is served at /live.
Index ¶
Constants ¶
const ( ModeAgent = "agent" // agent-driven (MCP inbox/reply) ModeServer = "server" // server-driven (in-app runner + Responder) )
Runtime modes.
const ( RoleUser = "user" RoleAgent = "agent" RoleSystem = "system" MsgPending = "pending" MsgProcessing = "processing" MsgDone = "done" MsgError = "error" )
Message roles / statuses.
Variables ¶
This section is empty.
Functions ¶
func RegisterChannel ¶
func RegisterChannel(name string, f ChannelFactory)
RegisterChannel registers an egress channel driver. Call from a driver package's init(); the app activates it by blank-importing the package. This mirrors togo-framework/notifications' RegisterChannel so a live channel and a notifications channel are authored the same way.
Types ¶
type Agent ¶
type Agent struct {
ID string `json:"id"`
Name string `json:"name"`
Persona string `json:"persona"` // system prompt / character
Provider string `json:"provider"` // claude | omni | echo
Workspace string `json:"workspace"` // Coder workspace name (agent-driven mode)
Status string `json:"status"` // idle | busy | offline
Token string `json:"token"` // bearer token for the MCP bridge (write-only)
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
Agent is a live AI agent: a persona bound to an execution backend (claude or omni, typically running inside its own Coder workspace) and addressed by a scoped token. The token authenticates the agent's MCP bridge to /inbox and /reply so it can read prompts and push responses.
type Channel ¶
type Channel interface {
// Name is the conversation.channel value this handles (e.g. "whatsapp").
Name() string
// Deliver pushes msg (an agent reply) to conv's external thread.
Deliver(ctx context.Context, conv Conversation, msg Message) error
}
Channel delivers an agent's reply out to where the conversation lives — the egress side. The built-in "table"/"chat" channels are in-app only (the reply is stored and streamed over the WS hub); third-party channels (whatsapp, slack, discord) are registered by driver plugins and push the reply to the provider. Delivery for the in-app channels is handled directly by the server, so a registered Channel only needs to cover its external transport.
type ChannelFactory ¶
ChannelFactory builds a Channel from the kernel (config/secrets from env).
type Conversation ¶
type Conversation struct {
ID string `json:"id"`
AgentID string `json:"agent_id"`
Channel string `json:"channel"` // table | chat | whatsapp | slack | discord
ExternalRef string `json:"external_ref"` // provider thread id (whatsapp msisdn, …)
Title string `json:"title"`
Status string `json:"status"` // open | closed
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
Conversation is one thread with an agent on one channel. external_ref binds it to a third-party thread (a WhatsApp number, a Slack thread ts, …) so inbound provider callbacks can be routed back to the right conversation.
type Message ¶
type Message struct {
ID string `json:"id"`
ConversationID string `json:"conversation_id"`
Role string `json:"role"` // user | agent | system
Body string `json:"body"`
Status string `json:"status"` // pending | processing | done | error
Meta string `json:"meta"` // opaque JSON
ClaimedBy string `json:"claimed_by"`
ClaimedAt string `json:"claimed_at"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
Message is one turn. role=user with status=pending is an inbound prompt waiting to be answered; role=agent is the response. Inserting a user Message is "push a prompt to the table".
type Responder ¶
type Responder interface {
Respond(ctx context.Context, agent Agent, conv Conversation, history []Message, prompt Message) (string, error)
}
Responder produces an agent reply for a prompt in server-driven mode. The loop hands it the agent, the conversation, the full prior transcript and the new user message; it returns the reply text. Implementations: echoResponder (deterministic, for tests/demos), claudeResponder (shells `claude -p`), and slotResponder (reuses the togo `impl`/`exec` provider slots, i.e. omnigent inside a Coder workspace). In agent-driven mode no Responder runs — the agent's own MCP bridge calls /reply instead.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the public handle channel drivers and app code use to drive the live plugin. Retrieve it with FromKernel(k). The plugin publishes itself into the kernel container during Boot.
func FromKernel ¶
FromKernel returns the live Service if the plugin is installed.
func (*Service) Ingest ¶
Ingest turns an inbound third-party message into a user prompt on the right conversation. It routes by (channel, externalRef): an existing conversation is reused, otherwise a new one is opened against the channel's default agent (LIVE_CHANNEL_AGENT, else the first registered agent). This is the entry point an inbound channel webhook (WhatsApp/Slack/…) calls. The reply is later delivered back out through the matching Channel.Deliver.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
live-mcp
command
Command live-mcp is the MCP bridge an agent runs inside its Coder workspace to "come alive": it exposes tools the running claude/omni calls to read prompts and push replies through a togo app's live plugin.
|
Command live-mcp is the MCP bridge an agent runs inside its Coder workspace to "come alive": it exposes tools the running claude/omni calls to read prompts and push replies through a togo app's live plugin. |