Documentation
¶
Index ¶
- Constants
- func AIChatHandler(w http.ResponseWriter, r *http.Request)
- func AddTapHandler(w http.ResponseWriter, r *http.Request)
- func CopyAgentToLocalHandler(w http.ResponseWriter, r *http.Request)
- func DeleteAgentHandler(w http.ResponseWriter, r *http.Request)
- func FormatValidationErrors(errors []string) string
- func GetAgentHandler(w http.ResponseWriter, r *http.Request)
- func GetFlowSchema() string
- func GetMCPSettingsHandler(w http.ResponseWriter, r *http.Request)
- func GetMCPStoreServerHandler(w http.ResponseWriter, r *http.Request)
- func GetMCPStoreTagsHandler(w http.ResponseWriter, r *http.Request)
- func GetMCPToolsets(ctx context.Context) []tool.Toolset
- func GetSettingsHandler(w http.ResponseWriter, r *http.Request)
- func GetSetupStatusHandler(w http.ResponseWriter, r *http.Request)
- func HandleChat(w http.ResponseWriter, r *http.Request)
- func InitToolsCache(ctx context.Context)
- func InstallFlowHandler(w http.ResponseWriter, r *http.Request)
- func InstallMCPStoreServerHandler(w http.ResponseWriter, r *http.Request)
- func ListAgentsHandler(w http.ResponseWriter, r *http.Request)
- func ListFlowStoreHandler(w http.ResponseWriter, r *http.Request)
- func ListMCPStoreHandler(w http.ResponseWriter, r *http.Request)
- func ListProviderModelsHandler(w http.ResponseWriter, r *http.Request)
- func ListTapsHandler(w http.ResponseWriter, r *http.Request)
- func ListToolsHandler(w http.ResponseWriter, r *http.Request)
- func RefreshToolsCache(ctx context.Context)
- func RegisterRoutes(router *mux.Router)
- func RemoveTapHandler(w http.ResponseWriter, r *http.Request)
- func SaveAgentHandler(w http.ResponseWriter, r *http.Request)
- func SendErrorSSE(w io.Writer, flusher http.Flusher, msg string)
- func SendSSE(w io.Writer, flusher http.Flusher, eventType string, data interface{})
- func UninstallFlowHandler(w http.ResponseWriter, r *http.Request)
- func UpdateFlowStoreHandler(w http.ResponseWriter, r *http.Request)
- func UpdateMCPSettingsHandler(w http.ResponseWriter, r *http.Request)
- func UpdateSettingsHandler(w http.ResponseWriter, r *http.Request)
- type AIChatRequest
- type AIChatResponse
- type AddTapRequest
- type AgentDetailResponse
- type AgentListItem
- type AgentListResponse
- type AppSettingsResponse
- type ChatMessage
- type ChatRequest
- type FlowInfo
- type FlowStoreListResponse
- type FlowValidationResult
- type GeneralSettings
- type MCPStoreInstallRequest
- type MCPStoreListResponse
- type ProviderSettings
- type SessionManager
- type SetupStatusResponse
- type TapInfo
- type ToolInfo
- type ToolsCache
- type ToolsListResponse
- type UpdateAppSettingsRequest
Constants ¶
const FlowSchema = `
# Astonish Agent Flow Schema
## Overview
An agent flow is defined in YAML with nodes (processing steps) and flow (edges connecting them).
## Basic Structure
` + "```yaml" + `
name: agent_name
description: What this agent does
model: gemini-2.0-flash # or gpt-4o, claude-3-5-sonnet, etc.
nodes:
- name: node_name
type: llm|input|tool|output|update_state
# type-specific fields...
flow:
- from: START
to: first_node
- from: first_node
to: second_node
- from: last_node
to: END
` + "```" + `
## Node Types
### 1. LLM Node (PREFERRED for tool usage)
AI processing with optional tool use.
- output_model: saves result to state for later nodes
- user_message: DISPLAY result to user (use this when user needs to see the response!)
` + "```yaml" + `
# LLM that shows answer to user (most common pattern)
- name: answer_question
type: llm
system: "You are a helpful assistant."
prompt: "{user_question}"
output_model:
answer: str
user_message:
- answer # This displays the LLM response to the user!
# LLM with tools
- name: search_and_summarize
type: llm
system: "You are a search assistant."
prompt: "Search for: {query}"
tools: true
tools_selection:
- tavily-search
output_model:
search_result: str
user_message:
- search_result # Show the result to user
` + "```" + `
### 2. Input Node
Collect user input. output_model is REQUIRED to store input in state.
**IMPORTANT: options behavior**
- WITHOUT options: User can type ANY text (free form input)
- WITH options: User can ONLY select from the listed options (no free text!)
` + "```yaml" + `
# Free text input - user can type anything
- name: get_question
type: input
prompt: "What is your question?"
output_model:
question: str
# Choice input - user can ONLY select from these options
- name: ask_continue
type: input
prompt: "Continue? (yes/no)"
output_model:
choice: str
options:
- "yes"
- "no"
# DYNAMIC options from state variable (from previous node output)
# Use this when a previous LLM node outputs a list and you want user to select from it
- name: list_items
type: llm
prompt: "List all available items"
output_model:
items: list # This outputs a list to state
tools: true
user_message:
- items
- name: select_item
type: input
prompt: "Select an item from the list above:"
output_model:
selected_item: str
options:
- items # Reference the state variable containing the list (NOT {items}!)
` + "```" + `
**CRITICAL for dynamic options:**
- Use ` + "`" + `options: [variable_name]` + "`" + ` to reference a list from state
- Do NOT use ` + "`" + `options: '{variable_name}'` + "`" + ` - this is WRONG!
- Do NOT use ` + "`" + `options: variable_name` + "`" + ` without brackets - this is WRONG!
- The variable must be a list type from a previous node's output_model
**DO NOT use options if you want the user to type free text!**
### 3. Tool Node (RARELY USED)
Execute a tool directly WITHOUT LLM intelligence. Only use when you need deterministic tool execution.
In most cases, prefer LLM node with tools: true instead.
` + "```yaml" + `
- name: run_fixed_command
type: tool
tools_selection:
- shell_command
args:
command: "ls -la"
output_model:
shell_result: str
` + "```" + `
### 4. Output Node
Display messages to user. Use user_message array with strings and state variable names.
Note: LLM responses are shown automatically, so output nodes are mainly for formatting/labeling.
` + "```yaml" + `
- name: show_result
type: output
user_message:
- "Answer:"
- answer
` + "```" + `
### 5. Update State Node
Modify state variables. Use source_variable OR value to set data, action to control how (overwrite/append),
and output_model to define the target variable and its type.
` + "```yaml" + `
# Overwrite a variable with a value
- name: set_flag
type: update_state
value: "true"
action: overwrite
output_model:
is_processed: string
# Copy from one variable to another
- name: save_result
type: update_state
source_variable: llm_response
action: overwrite
output_model:
saved_answer: string
# Append to a list
- name: add_to_history
type: update_state
source_variable: current_item
action: append
output_model:
history_list: list
` + "```" + `
## Flow Edges
### Simple Edge
` + "```yaml" + `
- from: node_a
to: node_b
` + "```" + `
### Conditional Edges
` + "```yaml" + `
- from: decision_node
edges:
- to: yes_path
condition: "lambda x: x['decision'] == 'yes'"
- to: no_path
condition: "lambda x: x['decision'] == 'no'"
` + "```" + `
### Loop (Back-edge)
IMPORTANT: Loops must point to actual nodes, NEVER to START!
` + "```yaml" + `
- from: ask_continue
edges:
- to: get_question # Loop back to the actual node, NOT to START!
condition: "lambda x: x['continue'] == 'yes'"
- to: END
condition: "lambda x: x['continue'] == 'no'"
` + "```" + `
## State & Templating
- Use {variable_name} to reference state (single braces, no spaces)
- Data flows through nodes via output_model which saves to state
- Access previous node outputs from state keys defined in output_model
## Patterns
### User Confirmation Pattern
Use INPUT node with options for reliable branching:
` + "```yaml" + `
- name: confirm
type: input
prompt: "Continue? (yes/no)"
output_model:
choice: str
options:
- "yes"
- "no"
` + "```" + `
Then use in conditional edge: ` + "`" + `condition: "lambda x: x['choice'] == 'yes'"` + "`" + `
### Displaying LLM Response
Always add user_message when the user should see the output:
` + "```yaml" + `
- name: process
type: llm
prompt: "{user_input}"
output_model:
result: str
user_message:
- result # This shows the response to the user
` + "```" + `
## Anti-Patterns (DO NOT DO)
❌ Using LLM to check yes/no conditions - unpredictable output breaks edges
❌ Creating "check_exit" or "check_quit" nodes - use input with options instead
❌ Missing user_message on LLM nodes - user won't see the response
❌ Using LLM output in conditional edges - conditions may never match
## Rules
1. Flow must start from START and end at END
2. START and END are VIRTUAL nodes - they are NOT actual nodes you define
3. You can ONLY use "from: START" to begin the flow - NEVER use "to: START"
4. Loops must point to actual node names (e.g., "to: get_question"), NEVER to START
5. All node names must be unique
6. Use output_model to pass data between nodes
7. ALWAYS include user_message on LLM nodes when user should see output
8. For branching/loops, use INPUT with options - gives reliable condition values
9. NEVER use LLM output in conditional edges - it's unpredictable
`
FlowSchema contains the schema documentation for AI to understand flow structure
Variables ¶
This section is empty.
Functions ¶
func AIChatHandler ¶
func AIChatHandler(w http.ResponseWriter, r *http.Request)
AIChatHandler handles AI chat requests
func AddTapHandler ¶ added in v1.2.0
func AddTapHandler(w http.ResponseWriter, r *http.Request)
AddTapHandler handles POST /api/flow-store/taps
func CopyAgentToLocalHandler ¶ added in v1.2.0
func CopyAgentToLocalHandler(w http.ResponseWriter, r *http.Request)
CopyAgentToLocalHandler handles POST /api/agents/{name}/copy-to-local Copies a store flow to the user's local agents directory for editing
func DeleteAgentHandler ¶
func DeleteAgentHandler(w http.ResponseWriter, r *http.Request)
DeleteAgentHandler handles DELETE /api/agents/{name}
func FormatValidationErrors ¶
FormatValidationErrors formats validation errors for LLM feedback
func GetAgentHandler ¶
func GetAgentHandler(w http.ResponseWriter, r *http.Request)
GetAgentHandler handles GET /api/agents/{name}
func GetFlowSchema ¶
func GetFlowSchema() string
GetFlowSchema returns the schema as a string for AI context
func GetMCPSettingsHandler ¶
func GetMCPSettingsHandler(w http.ResponseWriter, r *http.Request)
GetMCPSettingsHandler handles GET /api/settings/mcp
func GetMCPStoreServerHandler ¶ added in v1.1.0
func GetMCPStoreServerHandler(w http.ResponseWriter, r *http.Request)
GetMCPStoreServerHandler handles GET /api/mcp-store/{id}
func GetMCPStoreTagsHandler ¶ added in v1.1.0
func GetMCPStoreTagsHandler(w http.ResponseWriter, r *http.Request)
GetMCPStoreTagsHandler handles GET /api/mcp-store/tags
func GetMCPToolsets ¶ added in v1.1.0
GetMCPToolsets returns the cached MCP toolsets, initializing if needed
func GetSettingsHandler ¶
func GetSettingsHandler(w http.ResponseWriter, r *http.Request)
GetSettingsHandler handles GET /api/settings/config
func GetSetupStatusHandler ¶ added in v1.0.7
func GetSetupStatusHandler(w http.ResponseWriter, r *http.Request)
GetSetupStatusHandler handles GET /api/settings/status
func HandleChat ¶
func HandleChat(w http.ResponseWriter, r *http.Request)
HandleChat handles the /api/chat endpoint with SSE streaming
func InitToolsCache ¶
InitToolsCache initializes the tools cache at server startup
func InstallFlowHandler ¶ added in v1.2.0
func InstallFlowHandler(w http.ResponseWriter, r *http.Request)
InstallFlowHandler handles POST /api/flow-store/{tap}/{flow}/install
func InstallMCPStoreServerHandler ¶ added in v1.1.0
func InstallMCPStoreServerHandler(w http.ResponseWriter, r *http.Request)
InstallMCPStoreServerHandler handles POST /api/mcp-store/{id}/install Adds the MCP server configuration to the user's MCP config
func ListAgentsHandler ¶
func ListAgentsHandler(w http.ResponseWriter, r *http.Request)
ListAgentsHandler handles GET /api/agents
func ListFlowStoreHandler ¶ added in v1.2.0
func ListFlowStoreHandler(w http.ResponseWriter, r *http.Request)
ListFlowStoreHandler handles GET /api/flow-store Returns all taps and flows
func ListMCPStoreHandler ¶ added in v1.1.0
func ListMCPStoreHandler(w http.ResponseWriter, r *http.Request)
ListMCPStoreHandler handles GET /api/mcp-store Supports query parameter ?q=<search query> Only returns servers with valid configs (installable)
func ListProviderModelsHandler ¶
func ListProviderModelsHandler(w http.ResponseWriter, r *http.Request)
ListProviderModelsHandler handles GET /api/providers/{providerId}/models
func ListTapsHandler ¶ added in v1.2.0
func ListTapsHandler(w http.ResponseWriter, r *http.Request)
ListTapsHandler handles GET /api/flow-store/taps
func ListToolsHandler ¶
func ListToolsHandler(w http.ResponseWriter, r *http.Request)
ListToolsHandler handles GET /api/tools
func RefreshToolsCache ¶
RefreshToolsCache forces a refresh of the tools cache
func RegisterRoutes ¶
RegisterRoutes registers the API routes on a router
func RemoveTapHandler ¶ added in v1.2.0
func RemoveTapHandler(w http.ResponseWriter, r *http.Request)
RemoveTapHandler handles DELETE /api/flow-store/taps/{name}
func SaveAgentHandler ¶
func SaveAgentHandler(w http.ResponseWriter, r *http.Request)
SaveAgentHandler handles PUT /api/agents/{name}
func SendErrorSSE ¶
SendErrorSSE sends an error event
func UninstallFlowHandler ¶ added in v1.2.0
func UninstallFlowHandler(w http.ResponseWriter, r *http.Request)
UninstallFlowHandler handles DELETE /api/flow-store/{tap}/{flow}
func UpdateFlowStoreHandler ¶ added in v1.2.0
func UpdateFlowStoreHandler(w http.ResponseWriter, r *http.Request)
UpdateFlowStoreHandler handles POST /api/flow-store/update
func UpdateMCPSettingsHandler ¶
func UpdateMCPSettingsHandler(w http.ResponseWriter, r *http.Request)
UpdateMCPSettingsHandler handles PUT /api/settings/mcp
func UpdateSettingsHandler ¶
func UpdateSettingsHandler(w http.ResponseWriter, r *http.Request)
UpdateSettingsHandler handles PUT /api/settings/config
Types ¶
type AIChatRequest ¶
type AIChatRequest struct {
Message string `json:"message"`
Context string `json:"context"` // "create_flow" | "modify_nodes" | "node_config"
CurrentYAML string `json:"currentYaml"` // Current flow state
SelectedNodes []string `json:"selectedNodes"` // For node operations
History []ChatMessage `json:"history"` // Conversation history
}
AIChatRequest is the request body for AI chat
type AIChatResponse ¶
type AIChatResponse struct {
Message string `json:"message"` // AI response text
ProposedYAML string `json:"proposedYaml"` // Generated/modified YAML (if any)
Action string `json:"action"` // "preview" | "apply" | "info"
Error string `json:"error,omitempty"`
}
AIChatResponse is the response from AI chat
type AddTapRequest ¶ added in v1.2.0
type AddTapRequest struct {
URL string `json:"url"` // e.g., "company" or "company/repo"
Alias string `json:"alias"` // Optional custom name
}
AddTapRequest is the request for POST /api/flow-store/taps
type AgentDetailResponse ¶
type AgentDetailResponse struct {
Name string `json:"name"`
Source string `json:"source"`
YAML string `json:"yaml"`
Config *config.AgentConfig `json:"config,omitempty"`
}
AgentDetailResponse is the response for GET /api/agents/:name
type AgentListItem ¶
type AgentListItem struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Source string `json:"source"` // "system", "local", or "store"
HasError bool `json:"hasError,omitempty"`
ErrorMessage string `json:"errorMessage,omitempty"`
IsReadOnly bool `json:"isReadOnly,omitempty"` // True for store flows
TapName string `json:"tapName,omitempty"` // For store flows: which tap
}
AgentListItem represents an agent in the list response
type AgentListResponse ¶
type AgentListResponse struct {
Agents []AgentListItem `json:"agents"`
}
AgentListResponse is the response for GET /api/agents
type AppSettingsResponse ¶
type AppSettingsResponse struct {
General GeneralSettings `json:"general"`
Providers []ProviderSettings `json:"providers"`
}
AppSettingsResponse is the response for GET /api/settings/config
type ChatMessage ¶
type ChatMessage struct {
Role string `json:"role"` // "user" | "assistant"
Content string `json:"content"`
}
ChatMessage represents a message in the conversation
type ChatRequest ¶
type ChatRequest struct {
AgentID string `json:"agentId"`
Message string `json:"message"` // User input
SessionID string `json:"sessionId"`
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
}
ChatRequest represents the request body for /api/chat
type FlowInfo ¶ added in v1.2.0
type FlowInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Tags []string `json:"tags"`
TapName string `json:"tapName"`
Installed bool `json:"installed"`
FullName string `json:"fullName"` // tap/flow or just flow for official
}
FlowInfo represents a flow for the UI
type FlowStoreListResponse ¶ added in v1.2.0
FlowStoreListResponse is the response for GET /api/flow-store
type FlowValidationResult ¶
FlowValidationResult contains the result of validating a flow YAML
func ValidateFlowYAML ¶
func ValidateFlowYAML(yamlStr string, availableTools []ToolInfo) FlowValidationResult
ValidateFlowYAML validates the generated flow YAML against the schema rules
type GeneralSettings ¶
type GeneralSettings struct {
DefaultProvider string `json:"default_provider"`
DefaultProviderDisplayName string `json:"default_provider_display_name"`
DefaultModel string `json:"default_model"`
}
GeneralSettings represents the general app settings
type MCPStoreInstallRequest ¶ added in v1.1.0
type MCPStoreInstallRequest struct {
ServerName string `json:"serverName,omitempty"` // Optional: custom name for the server
Env map[string]string `json:"env,omitempty"` // Optional: environment variable overrides
}
MCPStoreInstallRequest is the request for POST /api/mcp-store/:id/install
type MCPStoreListResponse ¶ added in v1.1.0
type MCPStoreListResponse struct {
Servers []mcpstore.Server `json:"servers"`
Total int `json:"total"`
}
MCPStoreListResponse is the response for GET /api/mcp-store
type ProviderSettings ¶
type ProviderSettings struct {
Name string `json:"name"`
DisplayName string `json:"display_name"`
Configured bool `json:"configured"`
Fields map[string]string `json:"fields"` // Masked values for display
}
ProviderSettings represents a provider's configuration (masked)
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager manages active sessions
func GetSessionManager ¶
func GetSessionManager() *SessionManager
GetSessionManager returns the singleton session manager
type SetupStatusResponse ¶ added in v1.0.7
type SetupStatusResponse struct {
SetupRequired bool `json:"setupRequired"`
HasDefaultProvider bool `json:"hasDefaultProvider"`
HasDefaultModel bool `json:"hasDefaultModel"`
ConfiguredProviders []string `json:"configuredProviders"`
}
SetupStatusResponse represents the setup status for the wizard
type TapInfo ¶ added in v1.2.0
type TapInfo struct {
Name string `json:"name"`
URL string `json:"url"`
IsOfficial bool `json:"isOfficial"`
}
TapInfo represents a tap for the UI
type ToolInfo ¶
type ToolInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Source string `json:"source"` // "internal" or MCP server name
}
ToolInfo represents a tool in the list response
type ToolsCache ¶
type ToolsCache struct {
// contains filtered or unexported fields
}
ToolsCache holds cached tool information to avoid re-initializing MCP on every request
type ToolsListResponse ¶
type ToolsListResponse struct {
Tools []ToolInfo `json:"tools"`
}
ToolsListResponse is the response for GET /api/tools
type UpdateAppSettingsRequest ¶
type UpdateAppSettingsRequest struct {
General *GeneralSettings `json:"general,omitempty"`
Providers map[string]map[string]string `json:"providers,omitempty"`
}
UpdateAppSettingsRequest is the request for PUT /api/settings/config