Documentation
¶
Index ¶
- Constants
- func AIChatHandler(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 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 ListAgentsHandler(w http.ResponseWriter, r *http.Request)
- func ListProviderModelsHandler(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 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 UpdateMCPSettingsHandler(w http.ResponseWriter, r *http.Request)
- func UpdateSettingsHandler(w http.ResponseWriter, r *http.Request)
- type AIChatRequest
- type AIChatResponse
- type AgentDetailResponse
- type AgentListItem
- type AgentListResponse
- type AppSettingsResponse
- type ChatMessage
- type ChatRequest
- type FlowValidationResult
- type GeneralSettings
- type ProviderSettings
- type SessionManager
- type SetupStatusResponse
- 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"
` + "```" + `
**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 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 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 ListAgentsHandler ¶
func ListAgentsHandler(w http.ResponseWriter, r *http.Request)
ListAgentsHandler handles GET /api/agents
func ListProviderModelsHandler ¶
func ListProviderModelsHandler(w http.ResponseWriter, r *http.Request)
ListProviderModelsHandler handles GET /api/providers/{providerId}/models
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 SaveAgentHandler ¶
func SaveAgentHandler(w http.ResponseWriter, r *http.Request)
SaveAgentHandler handles PUT /api/agents/{name}
func SendErrorSSE ¶
SendErrorSSE sends an error event
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 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" or "local"
}
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 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 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 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