diff --git a/core/config/model_config.go b/core/config/model_config.go index b8a2a4ffa..1750fb3ac 100644 --- a/core/config/model_config.go +++ b/core/config/model_config.go @@ -99,6 +99,10 @@ type AgentConfig struct { EnablePlanning bool `yaml:"enable_planning,omitempty" json:"enable_planning,omitempty"` EnableMCPPrompts bool `yaml:"enable_mcp_prompts,omitempty" json:"enable_mcp_prompts,omitempty"` EnablePlanReEvaluator bool `yaml:"enable_plan_re_evaluator,omitempty" json:"enable_plan_re_evaluator,omitempty"` + DisableSinkState bool `yaml:"disable_sink_state,omitempty" json:"disable_sink_state,omitempty"` + LoopDetection int `yaml:"loop_detection,omitempty" json:"loop_detection,omitempty"` + MaxAdjustmentAttempts int `yaml:"max_adjustment_attempts,omitempty" json:"max_adjustment_attempts,omitempty"` + ForceReasoningTool bool `yaml:"force_reasoning_tool,omitempty" json:"force_reasoning_tool,omitempty"` } func (c *MCPConfig) MCPConfigFromYAML() (MCPGenericConfig[MCPRemoteServers], MCPGenericConfig[MCPSTDIOServers], error) { @@ -704,7 +708,7 @@ func (c *ModelConfig) BuildCogitoOptions() []cogito.Option { // Apply agent configuration options if c.Agent.EnableReasoning { - cogitoOpts = append(cogitoOpts, cogito.EnableToolReasoner) + cogitoOpts = append(cogitoOpts, cogito.WithForceReasoning()) } if c.Agent.EnablePlanning { @@ -727,5 +731,21 @@ func (c *ModelConfig) BuildCogitoOptions() []cogito.Option { cogitoOpts = append(cogitoOpts, cogito.WithMaxAttempts(c.Agent.MaxAttempts)) } + if c.Agent.DisableSinkState { + cogitoOpts = append(cogitoOpts, cogito.DisableSinkState) + } + + if c.Agent.LoopDetection != 0 { + cogitoOpts = append(cogitoOpts, cogito.WithLoopDetection(c.Agent.LoopDetection)) + } + + if c.Agent.MaxAdjustmentAttempts != 0 { + cogitoOpts = append(cogitoOpts, cogito.WithMaxAdjustmentAttempts(c.Agent.MaxAdjustmentAttempts)) + } + + if c.Agent.ForceReasoningTool { + cogitoOpts = append(cogitoOpts, cogito.WithForceReasoningTool()) + } + return cogitoOpts } diff --git a/core/http/endpoints/localai/mcp.go b/core/http/endpoints/localai/mcp.go index 9962ab533..ff39e7dad 100644 --- a/core/http/endpoints/localai/mcp.go +++ b/core/http/endpoints/localai/mcp.go @@ -102,7 +102,7 @@ func MCPEndpoint(cl *config.ModelConfigLoader, ml *model.ModelLoader, evaluator // Build fragment from messages fragment := cogito.NewEmptyFragment() for _, message := range input.Messages { - fragment = fragment.AddMessage(message.Role, message.StringContent) + fragment = fragment.AddMessage(cogito.MessageRole(message.Role), message.StringContent) } _, port, err := net.SplitHostPort(appConfig.APIAddress) diff --git a/core/http/endpoints/openresponses/responses.go b/core/http/endpoints/openresponses/responses.go index ef178df03..8a5e418d6 100644 --- a/core/http/endpoints/openresponses/responses.go +++ b/core/http/endpoints/openresponses/responses.go @@ -927,7 +927,7 @@ func handleBackgroundMCPResponse(ctx context.Context, store *ResponseStore, resp // Build fragment from messages fragment := cogito.NewEmptyFragment() for _, message := range openAIReq.Messages { - fragment = fragment.AddMessage(message.Role, message.StringContent) + fragment = fragment.AddMessage(cogito.MessageRole(message.Role), message.StringContent) } fragmentPtr := &fragment @@ -2484,7 +2484,7 @@ func handleMCPResponse(c echo.Context, responseID string, createdAt int64, input // Build fragment from messages fragment := cogito.NewEmptyFragment() for _, message := range openAIReq.Messages { - fragment = fragment.AddMessage(message.Role, message.StringContent) + fragment = fragment.AddMessage(cogito.MessageRole(message.Role), message.StringContent) } fragmentPtr := &fragment diff --git a/docs/content/features/mcp.md b/docs/content/features/mcp.md index 0515d2d3e..23193cb66 100644 --- a/docs/content/features/mcp.md +++ b/docs/content/features/mcp.md @@ -78,12 +78,16 @@ mcp: } agent: - max_attempts: 3 # Maximum number of tool execution attempts - max_iterations: 3 # Maximum number of reasoning iterations - enable_reasoning: true # Enable tool reasoning capabilities - enable_planning: false # Enable auto-planning capabilities - enable_mcp_prompts: false # Enable MCP prompts + max_attempts: 3 # Maximum number of tool execution attempts + max_iterations: 3 # Maximum number of reasoning iterations + enable_reasoning: true # Enable tool reasoning capabilities + enable_planning: false # Enable auto-planning capabilities + enable_mcp_prompts: false # Enable MCP prompts enable_plan_re_evaluator: false # Enable plan re-evaluation + disable_sink_state: false # Disable sink state behavior + loop_detection: 3 # Loop detection sensitivity level + max_adjustment_attempts: 5 # Maximum adjustment attempts for tool calls + force_reasoning_tool: false # Force reasoning tool usage ``` ### Configuration Options @@ -104,12 +108,21 @@ Configure local command-based MCP servers: #### Agent Configuration (`agent`) Configure agent behavior and tool execution: -- **`max_attempts`**: Maximum number of tool execution attempts (default: 3) -- **`max_iterations`**: Maximum number of reasoning iterations (default: 3) -- **`enable_reasoning`**: Enable tool reasoning capabilities (default: false) -- **`enable_planning`**: Enable auto-planning capabilities (default: false) -- **`enable_mcp_prompts`**: Enable MCP prompts (default: false) -- **`enable_plan_re_evaluator`**: Enable plan re-evaluation (default: false) +**Execution Control** +- **`max_attempts`**: Maximum number of tool execution attempts (default: 3). Higher values provide more resilience but may increase response time. +- **`max_iterations`**: Maximum number of reasoning iterations (default: 3). More iterations allow for complex multi-step problem solving. +- **`loop_detection`**: Loop detection sensitivity level (default: 0, disabled). Set to a positive integer (e.g., 3) to enable loop detection and prevent infinite execution cycles. +- **`max_adjustment_attempts`**: Maximum adjustment attempts for tool calls (default: 5). Prevents infinite loops when adjusting tool call parameters. + +**Reasoning and Planning** +- **`enable_reasoning`**: Enable tool reasoning capabilities (default: false). When enabled, the agent uses advanced reasoning to better understand tool results. +- **`enable_planning`**: Enable auto-planning capabilities (default: false). When enabled, breaks down complex tasks into manageable steps. +- **`disable_sink_state`**: Disable sink state behavior (default: false). When enabled, prevents the agent from entering a sink state. +- **`force_reasoning_tool`**: Force reasoning tool usage (default: false). When enabled, always use the reasoning tool in the agent's reasoning process. + +**MCP Integration** +- **`enable_mcp_prompts`**: Enable MCP prompts (default: false). When enabled, uses specialized prompts exposed by MCP servers. +- **`enable_plan_re_evaluator`**: Enable plan re-evaluation (default: false). When enabled, dynamically adjusts execution plans based on results. ## Usage @@ -186,9 +199,13 @@ The `agent` section controls how the AI model interacts with MCP tools: ### Execution Control - **`max_attempts`**: Limits how many times a tool can be retried if it fails. Higher values provide more resilience but may increase response time. - **`max_iterations`**: Controls the maximum number of reasoning cycles the agent can perform. More iterations allow for complex multi-step problem solving. +- **`loop_detection`**: Set to a positive integer (e.g., 3) to enable loop detection and prevent infinite execution cycles. Default is 0 (disabled). +- **`max_adjustment_attempts`**: Limits the number of times the agent can adjust tool call parameters. Prevents infinite loops during tool execution (default: 5). ### Reasoning Capabilities - **`enable_reasoning`**: When enabled, the agent uses advanced reasoning to better understand tool results and plan next steps. +- **`force_reasoning_tool`**: When enabled, forces the agent to always use the reasoning tool in its reasoning process, ensuring explicit reasoning steps. +- **`disable_sink_state`**: When enabled, prevents the agent from entering a sink state where it stops making progress. ### Planning Capabilities - **`enable_planning`**: When enabled, the agent uses auto-planning to break down complex tasks into manageable steps and execute them systematically. The agent will automatically detect when planning is needed. @@ -198,8 +215,9 @@ The `agent` section controls how the AI model interacts with MCP tools: ### Recommended Settings - **Simple tasks**: `max_attempts: 2`, `max_iterations: 2`, `enable_reasoning: false`, `enable_planning: false` - **Complex tasks**: `max_attempts: 5`, `max_iterations: 5`, `enable_reasoning: true`, `enable_planning: true`, `enable_mcp_prompts: true` -- **Advanced planning**: `max_attempts: 5`, `max_iterations: 5`, `enable_reasoning: true`, `enable_planning: true`, `enable_mcp_prompts: true`, `enable_plan_re_evaluator: true` +- **Advanced planning**: `max_attempts: 5`, `max_iterations: 5`, `enable_reasoning: true`, `enable_planning: true`, `enable_mcp_prompts: true`, `enable_plan_re_evaluator: true`, `loop_detection: 3` - **Development/Debugging**: `max_attempts: 1`, `max_iterations: 1`, `enable_reasoning: true`, `enable_planning: true` +- **Aggressive loop prevention**: `max_attempts: 5`, `max_iterations: 5`, `loop_detection: 2`, `max_adjustment_attempts: 3`, `force_reasoning_tool: true` ## How It Works diff --git a/go.mod b/go.mod index 1fcf2e1ec..c27122bb3 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/mholt/archiver/v3 v3.5.1 github.com/microcosm-cc/bluemonday v1.0.27 github.com/modelcontextprotocol/go-sdk v1.3.0 - github.com/mudler/cogito v0.8.2-0.20260214201734-da0d4ceb2b44 + github.com/mudler/cogito v0.9.1-0.20260217143801-bb7f986ed2c7 github.com/mudler/edgevpn v0.31.1 github.com/mudler/go-processmanager v0.1.0 github.com/mudler/memory v0.0.0-20251216220809-d1256471a6c2 diff --git a/go.sum b/go.sum index f72a9952e..ee86d6c49 100644 --- a/go.sum +++ b/go.sum @@ -511,6 +511,8 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mudler/cogito v0.8.2-0.20260214201734-da0d4ceb2b44 h1:joGszpItINnZdoL/0p2077Wz2xnxMGRSRgYN5mS7I4c= github.com/mudler/cogito v0.8.2-0.20260214201734-da0d4ceb2b44/go.mod h1:6sfja3lcu2nWRzEc0wwqGNu/eCG3EWgij+8s7xyUeQ4= +github.com/mudler/cogito v0.9.1-0.20260217143801-bb7f986ed2c7 h1:z3AcM7LbaQb+C955JdSXksHB9B0uWGQpdgl05gJM+9Y= +github.com/mudler/cogito v0.9.1-0.20260217143801-bb7f986ed2c7/go.mod h1:6sfja3lcu2nWRzEc0wwqGNu/eCG3EWgij+8s7xyUeQ4= github.com/mudler/edgevpn v0.31.1 h1:7qegiDWd0kAg6ljhNHxqvp8hbo/6BbzSdbb7/2WZfiY= github.com/mudler/edgevpn v0.31.1/go.mod h1:ftV5B0nKFzm4R8vR80UYnCb2nf7lxCRgAALxUEEgCf8= github.com/mudler/go-piper v0.0.0-20241023091659-2494246fd9fc h1:RxwneJl1VgvikiX28EkpdAyL4yQVnJMrbquKospjHyA=