项目文件夹

文件
T
Asim Aslam e416ea4a75 Enhance agent workflows with guardrails and documentation updates (#2952)
* docs: map go-micro onto Anthropic's workflows-vs-agents taxonomy

- new guide 'Agents and Workflows': adopts Anthropic's Building Effective
  Agents vocabulary — workflow (predefined path) = flow, agent (dynamic
  self-direction) = agent — maps the augmented-LLM building block and the
  five workflow patterns onto go-micro, and shows routing (chat router)
  and orchestrator-workers (conductor + plan/delegate) are already native.
- flow package doc reframed as a workflow (predefined path) per the same
  taxonomy, with guidance on flow vs agent.
- nav + README link the new guide.

* feat: agent guardrails — step limit and tool approval hook

Anthropic's Building Effective Agents stresses stopping conditions and
human-in-the-loop checkpoints for autonomous agents. Add both as plain
options enforced at the tool-handler choke point — no provider changes,
no new abstraction:

- MaxSteps(n): bound tool executions per Ask; beyond the limit, actions
  are refused and the model is told to stop and summarize.
- ApproveTool(fn): gate each action before it runs; returning false
  blocks it and surfaces the reason to the model. The internal plan tool
  is never gated.

Exposed at the micro package (AgentMaxSteps, AgentApproveTool, ApproveFunc).
Tests cover the limit, blocking, and that plan is not gated. Guardrails
section of the agents-and-workflows guide updated from 'active work' to
documented options.

* feat: flow can dispatch to an agent (flow triggers, agent reasons)

Unify the engine without collapsing the workflow/agent distinction. A
Flow with Agent set hands each event's rendered prompt to a named
registered agent over RPC (Agent.Chat) instead of running its own LLM
step — so the workflow stays the deterministic trigger and the agent is
the reasoning engine, with its plan, delegate, memory, and guardrails.
A plain flow is unchanged (single augmented-LLM step).

- flow.Agent(name) / micro.FlowAgent(name); flow stores the client and
  skips model setup when dispatching.
- test: dispatch routes to comms.Agent.Chat with the rendered prompt and
  records the reply.
- guide: 'Flow triggers, Agent reasons' section.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-08 08:32:32 +01:00

115 行
3.1 KiB
Go

package agent
import (
"go-micro.dev/v5/client"
"go-micro.dev/v5/registry"
"go-micro.dev/v5/store"
)
// Option configures an Agent.
type Option func(*Options)
// ApproveFunc decides whether an agent may execute a tool call before it
// runs. Returning false blocks the call; the reason is shown to the
// model so it can adapt. Use it for human-in-the-loop approval or policy
// checks. It is called for actions (service tools and delegate), not for
// the internal plan tool.
type ApproveFunc func(tool string, input map[string]any) (approved bool, reason string)
// Options holds agent configuration.
type Options struct {
Name string
Services []string
Prompt string
Provider string
Model string
APIKey string
Registry registry.Registry
Client client.Client
Store store.Store
HistoryLimit int
// MaxSteps bounds the number of tool executions per Ask (0 =
// unbounded). Once exceeded, further tool calls are refused and the
// model is told to stop and summarize. A stopping condition.
MaxSteps int
// Approve gates each action before it runs. Nil = allow all.
Approve ApproveFunc
}
func newOptions(opts ...Option) Options {
o := Options{
Registry: registry.DefaultRegistry,
Client: client.DefaultClient,
Store: store.DefaultStore,
HistoryLimit: 50,
}
for _, opt := range opts {
opt(&o)
}
return o
}
// Name sets the agent name.
func Name(n string) Option {
return func(o *Options) { o.Name = n }
}
// Services sets which services this agent manages.
func Services(names ...string) Option {
return func(o *Options) { o.Services = names }
}
// Prompt sets the system prompt.
func Prompt(p string) Option {
return func(o *Options) { o.Prompt = p }
}
// Provider sets the LLM provider.
func Provider(p string) Option {
return func(o *Options) { o.Provider = p }
}
// Model sets the LLM model name.
func Model(m string) Option {
return func(o *Options) { o.Model = m }
}
// APIKey sets the API key for the LLM provider.
func APIKey(k string) Option {
return func(o *Options) { o.APIKey = k }
}
// WithRegistry sets the service registry.
func WithRegistry(r registry.Registry) Option {
return func(o *Options) { o.Registry = r }
}
// WithClient sets the RPC client.
func WithClient(c client.Client) Option {
return func(o *Options) { o.Client = c }
}
// WithStore sets the store for agent memory.
func WithStore(s store.Store) Option {
return func(o *Options) { o.Store = s }
}
// HistoryLimit sets the max conversation messages to retain.
func HistoryLimit(n int) Option {
return func(o *Options) { o.HistoryLimit = n }
}
// MaxSteps bounds tool executions per Ask (0 = unbounded). A stopping
// condition: beyond the limit, tool calls are refused and the model is
// told to stop and summarize.
func MaxSteps(n int) Option {
return func(o *Options) { o.MaxSteps = n }
}
// ApproveTool sets a human-in-the-loop / policy hook called before each
// action (service tools and delegate). Returning false blocks the call.
func ApproveTool(fn ApproveFunc) Option {
return func(o *Options) { o.Approve = fn }
}