we-promise/sure · error · Assistant::Error
External assistant is not configured. Set the URL and token
Error message
External assistant is not configured. Set the URL and token in Settings > Self-Hosting or via environment variables.
What it means
Assistant::External is the bridge to a self-hosted external agent: it reads EXTERNAL_ASSISTANT_URL/TOKEN/AGENT_ID from ENV first, falling back to Setting values (session key EXTERNAL_ASSISTANT_SESSION_KEY, default agent 'main'). respond_to first checks self.class.configured?; if no URL or no token resolves from either source, it raises Assistant::Error with this guidance message pointing at Settings > Self-Hosting or environment variables. This fires before any network call — it is purely a configuration gate (URL and token are both required; agent_id defaults, session key defaults).
Source
Thrown at app/models/assistant/external.rb:41
allowed.split(",").map { |e| e.strip.downcase }.include?(user.email.downcase)
end
def config
Config.new(
url: ENV["EXTERNAL_ASSISTANT_URL"].presence || Setting.external_assistant_url.presence,
token: ENV["EXTERNAL_ASSISTANT_TOKEN"].presence || Setting.external_assistant_token.presence,
agent_id: ENV["EXTERNAL_ASSISTANT_AGENT_ID"].presence || Setting.external_assistant_agent_id.presence || "main",
session_key: ENV.fetch("EXTERNAL_ASSISTANT_SESSION_KEY", "agent:main:main")
)
end
end
def respond_to(message, assistant_message: nil)
response_completed = false
assistant_message ||= AssistantMessage.new(chat: chat, content: "", ai_model: "external-agent")
unless self.class.configured?
raise Assistant::Error,
"External assistant is not configured. Set the URL and token in Settings > Self-Hosting or via environment variables."
end
unless self.class.allowed_user?(chat.user)
raise Assistant::Error, "Your account is not authorized to use the external assistant."
end
client = build_client
messages = build_conversation_messages
model = client.chat(
messages: messages,
user: "sure-family-#{chat.user.family_id}"
) do |text|
assistant_message.append_text!(text)
end
if assistant_message.content.blank?View on GitHub (pinned to e69894adb9)
Solutions
- Set both values in ONE place consistently: either ENV (EXTERNAL_ASSISTANT_URL and EXTERNAL_ASSISTANT_TOKEN — plus optional EXTERNAL_ASSISTANT_AGENT_ID / EXTERNAL_ASSISTANT_SESSION_KEY) or Settings > Self-Hosting (External assistant URL + token)
- If using ENV, confirm the vars are visible to every process that runs chats (web and Sidekiq): ENV['EXTERNAL_ASSISTANT_URL'].present? in each context
- If using the UI, re-open Settings > Self-Hosting and verify the token field actually saved (it's encrypted/blanked on re-render)
- Verify in console: Assistant::External.configured? must return true before chatting (it checks exactly what respond_to checks)
Example fix
# before # .env.local has nothing; Settings UI never opened Assistant::External.new(chat).respond_to(message) # => Assistant::Error: External assistant is not configured. Set the URL and token in ... # after (either) # 1) ENV: EXTERNAL_ASSISTANT_URL=https://agents.internal EXTERNAL_ASSISTANT_TOKEN=secret # 2) UI: Settings > Self-Hosting > External assistant URL + token saved Assistant::External.configured? # => true Assistant::External.new(chat).respond_to(message)
Defensive patterns
Strategy: validation
Validate before calling
# Gate the UI/entry point on the same check respond_to uses
unless Assistant::External.configured?
# hide/disable the external agent option, or link to Settings > Self-Hosting
render json: { error: "external assistant not configured" }, status: :service_unavailable
end Type guard
def external_assistant_ready? Assistant::External.configured? end
Try / catch
rescue Assistant::Error => e
if e.message.include?("not configured")
# config problem, not a chat problem: link the user to Settings > Self-Hosting
chat.add_error(e)
else
raise
end
end Prevention
- Set URL and token together, in one source (ENV xor Settings UI)
- Verify ENV vars are present in web AND background processes after deploys
- Add a boot health check: fail fast at startup if the external agent is selected but unconfigured
- Smoke-test Assistant::External.configured? in your environment checklist
When it happens
Trigger: Selecting the external agent in the assistant UI on a fresh install (neither ENV nor Setting has URL/token); setting EXTERNAL_ASSISTANT_URL in ENV but forgetting EXTERNAL_ASSISTANT_TOKEN (presence check fails on token); configuring via Settings UI but the encrypted token Setting saved blank; deploying with dotenv in web but not in the Sidekiq/background process, so chats created from a job see a different (empty) environment; values present but whitespace-only (presence fails).
Common situations: Split ENV propagation between Rails server and background workers; the encrypted-attributes setting not persisted because the form key was omitted; migrating from ENV to UI settings (or back) and leaving both sides blank after a cleanup; staging configured, production not, and traffic hitting production.
Related errors
- No LLM provider configured that supports model '#{requested_
- Anthropic Base URL must be an http(s) URL.
- Anthropic Model is required when a custom Base URL is set.
- Your account is not authorized to use the external assistant
- External assistant returned an empty response.
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/db62f783f434971f.
Report an issue: GitHub.