micro/go-micro · error

agent: StreamAsk unsupported by implementation

Error message

agent: StreamAsk unsupported by implementation

What it means

StreamAsk is a helper that streams agent responses only when the underlying Agent implementation also implements a StreamAsk(context.Context, string) (AgentStream, error) method via an anonymous interface check. If the agent does not support streaming, this sentinel error is returned instead of a stream. It exists to let callers opt into streaming without requiring every Agent to implement it.

Source

Thrown at agent/stream.go:53

	Result   ai.ToolResult
	Response *Response
}

// AgentStream is a stream of tool execution events followed by final-answer chunks.
type AgentStream interface {
	Recv() (*StreamEvent, error)
	Close() error
}

// StreamAsk runs an agent Ask turn with tool start/end events and streams the final answer.
// It is additive for callers that hold the public Agent interface; concrete agents also
// expose the same method directly.
func StreamAsk(ctx context.Context, ag Agent, message string) (AgentStream, error) {
	streamer, ok := ag.(interface {
		StreamAsk(context.Context, string) (AgentStream, error)
	})
	if !ok {
		return nil, errors.New("agent: StreamAsk unsupported by implementation")
	}
	return streamer.StreamAsk(ctx, message)
}

// ResumeStreamAsk resumes a checkpointed agent run and emits the same event
// shape as StreamAsk. Completed runs are streamed from the persisted response;
// unfinished runs continue from their checkpoint and emit tool events for any
// work that still needs to run. Tool calls already recorded as done in the
// checkpoint are reused by the agent checkpoint wrapper and are not re-executed.
func ResumeStreamAsk(ctx context.Context, ag Agent, runID string) (AgentStream, error) {
	a, ok := ag.(*agentImpl)
	if !ok {
		return nil, errors.New("agent: ResumeStreamAsk unsupported by implementation")
	}
	return a.resumeStreamAsk(ctx, runID)
}

// StreamAsk runs tools like Ask, emits ToolStart/ToolEnd events as they execute,

View on GitHub (pinned to 24529f1404)

Solutions

  1. Use an agent implementation that supports streaming (e.g. the library's agentImpl)
  2. Check support first with a type assertion to interface{ StreamAsk(context.Context, string) (AgentStream, error) } and fall back to Ask
  3. Wrap custom agent types to forward StreamAsk to the inner agent

Example fix

// before
stream, err := agent.StreamAsk(ctx, myWrapper{inner: ag}, "hi")
// after
streamer, ok := ag.(interface{ StreamAsk(context.Context, string) (AgentStream, error) })
if !ok {
    resp, err := agent.Ask(ctx, ag, "hi") // fallback
} else {
    stream, err := streamer.StreamAsk(ctx, "hi")
}
Defensive patterns

Strategy: type-guard

Validate before calling

streamer, ok := ag.(interface{ StreamAsk(context.Context, string) (AgentStream, error) })
if !ok { /* fallback to Ask */ }

Type guard

func supportsStreamAsk(ag agent.Agent) bool {
    _, ok := ag.(interface{ StreamAsk(context.Context, string) (AgentStream, error) })
    return ok
}

Try / catch

stream, err := agent.StreamAsk(ctx, ag, msg)
if err != nil && strings.Contains(err.Error(), "unsupported by implementation") {
    resp, err := agent.Ask(ctx, ag, msg) // non-streaming fallback
}

Prevention

When it happens

Trigger: Calling agent.StreamAsk(ctx, ag, message) where ag is an Agent whose concrete type does not define a StreamAsk method (only plain Ask).

Common situations: Wrapping or decorating an agent with a custom type that forwards Ask but not StreamAsk; using an older or custom agent implementation predating streaming support; passing a mock/stub agent in tests.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/2f73b7f6b20fb69b. Report an issue: GitHub.