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

  1. Add at least one agent to config (agents.list entry with a model/provider) so the registry is non-empty
  2. Check startup logs for earlier agent-construction errors (bad provider, missing API key) that left the registry empty
  3. If you do not want periodic agent self-checks, disable the heartbeat feature instead of leaving it on
  4. 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

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


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/90d1f247a8394f6d. Report an issue: GitHub.