sipeed/picoclaw · error
no default agent for heartbeat
Error message
no default agent for heartbeat
What it means
HandleHeartbeat dispatches periodic heartbeat content through the default agent. AgentRegistry.GetDefaultAgent (pkg/agent/registry.go:174) returns the configured default, else any registered agent, else nil. This error means the registry is completely empty — no agents were constructed from config, so there is nothing to dispatch the heartbeat to.
Source
Thrown at pkg/agent/agent_message.go:81
}
return al.processMessage(ctx, msg)
}
func (al *AgentLoop) ProcessHeartbeat(
ctx context.Context,
content, channel, chatID string,
) (string, error) {
if err := al.ensureHooksInitialized(ctx); err != nil {
return "", err
}
if err := al.ensureMCPInitialized(ctx); err != nil {
return "", err
}
agent := al.GetRegistry().GetDefaultAgent()
if agent == nil {
return "", fmt.Errorf("no default agent for heartbeat")
}
dispatch := DispatchRequest{
SessionKey: "heartbeat",
UserMessage: content,
}
if channel != "" || chatID != "" {
dispatch.InboundContext = &bus.InboundContext{
Channel: channel,
ChatID: chatID,
ChatType: "direct",
SenderID: "heartbeat",
}
}
return al.runAgentLoop(ctx, agent, processOptions{
Dispatch: dispatch,
DefaultResponse: defaultResponse,
EnableSummary: false,
SendResponse: false,View on GitHub (pinned to 49183d7e8d)
Solutions
- Add at least one agent to config (agents.list entry with a model/provider) so the registry is non-empty
- Check startup logs for earlier agent-construction errors (bad provider, missing API key) that left the registry empty
- If you do not want periodic agent self-checks, disable the heartbeat feature instead of leaving it on
- In custom embeddings, register an agent with the registry before enabling heartbeats
Example fix
// config — before
"agents": { "defaults": {}, "list": [] }
// after
"agents": {
"defaults": { "model_name": "gpt-4o-mini", "provider": "openai" },
"list": [ { "id": "main", "model_name": "gpt-4o-mini", "provider": "openai" } ]
} Defensive patterns
Strategy: validation
Validate before calling
if al.GetRegistry().GetDefaultAgent() == nil {
return fmt.Errorf("no agents registered: add an agents.list entry before enabling heartbeat")
}
// only now start the heartbeat scheduler Prevention
- Gate heartbeat scheduling on a non-empty agent registry at startup
- Fail config validation when heartbeat is enabled but agents.list is empty
- Check agent construction logs after config changes — an empty registry is usually downstream of a provider error
When it happens
Trigger: The heartbeat timer fires (or HandleHeartbeat is called directly) while the AgentRegistry has zero agents: agents.list empty/absent in config, or agent construction failed earlier so nothing was registered.
Common situations: Minimal first-run config with providers but no agents section; heartbeat feature enabled while agents are disabled; agent construction silently skipped after a provider/model config error; unit tests building an AgentLoop without registry entries.
Related errors
- no agent available for route (agent_id=%s)
- no default agent for system message
- ✗ registry '%s' not found or not enabled. check your config
- channel %s not found
- failed to load MCP servers: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/90d1f247a8394f6d.
Report an issue: GitHub.