diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Agent.App/Logging/JsonLinesRuntimeObserver.cs | 2 | ||||
| -rw-r--r-- | src/Agent.Core/Runtime/AgentRuntime.cs | 8 | ||||
| -rw-r--r-- | src/Agent.Core/Tools/InternalToolDispatcher.cs | 2 | ||||
| -rw-r--r-- | src/Agent.Core/Tools/ToolPolicy.cs | 7 |
4 files changed, 15 insertions, 4 deletions
diff --git a/src/Agent.App/Logging/JsonLinesRuntimeObserver.cs b/src/Agent.App/Logging/JsonLinesRuntimeObserver.cs index b7cbd26..20ef88d 100644 --- a/src/Agent.App/Logging/JsonLinesRuntimeObserver.cs +++ b/src/Agent.App/Logging/JsonLinesRuntimeObserver.cs @@ -26,7 +26,7 @@ public sealed class JsonLinesRuntimeObserver(string logDirectory) : IAgentRuntim public void ToolResult(Guid taskId, string toolName, ToolExecutionResult result) => Write(new { timestamp = DateTimeOffset.UtcNow, task_id = taskId, event_name = "llm.tool_result", tool_name = toolName, - result.Success, result.ExternalEffect, result.Output, result.FailureFingerprint + result.Success, result.ExternalEffect, result.RetryAllowed, result.Output, result.FailureFingerprint }); private void Write(object value) diff --git a/src/Agent.Core/Runtime/AgentRuntime.cs b/src/Agent.Core/Runtime/AgentRuntime.cs index c2fa568..0fcf7d0 100644 --- a/src/Agent.Core/Runtime/AgentRuntime.cs +++ b/src/Agent.Core/Runtime/AgentRuntime.cs @@ -63,7 +63,11 @@ public sealed class AgentRuntime(TaskRegistry registry, IOllamaClient ollama, Ag { toolResult = await _tools.DispatchAsync(taskId, call.Function.Name, call.Function.Arguments, cancellationToken).ConfigureAwait(false); } - catch (Exception ex) when (ex is ToolValidationException or ArgumentException or UnauthorizedAccessException) + catch (UnauthorizedAccessException ex) + { + toolResult = new(false, ex.Message, false, $"{call.Function.Name}:{ex.GetType().Name}:{ex.Message}", RetryAllowed: false); + } + catch (Exception ex) when (ex is ToolValidationException or ArgumentException) { toolResult = new(false, ex.Message, false, $"{call.Function.Name}:{ex.GetType().Name}:{ex.Message}"); } @@ -72,6 +76,8 @@ public sealed class AgentRuntime(TaskRegistry registry, IOllamaClient ollama, Ag else unresolvedToolFailures[call.Function.Name] = toolResult.FailureFingerprint ?? toolResult.Output; if (toolResult.Success) successfulToolCalls[call.Function.Name] = successfulToolCalls.GetValueOrDefault(call.Function.Name) + 1; _observer.ToolResult(taskId, call.Function.Name, toolResult); + if (!toolResult.Success && !toolResult.RetryAllowed) + throw new InvalidOperationException($"Tool '{call.Function.Name}' was denied by sandbox policy and will not be retried: {toolResult.Output}"); failureFingerprint = toolResult.FailureFingerprint ?? failureFingerprint; messages.Add(new OllamaMessage("tool", toolResult.Output, ToolName: call.Function.Name)); } diff --git a/src/Agent.Core/Tools/InternalToolDispatcher.cs b/src/Agent.Core/Tools/InternalToolDispatcher.cs index 7302c1f..0dca5df 100644 --- a/src/Agent.Core/Tools/InternalToolDispatcher.cs +++ b/src/Agent.Core/Tools/InternalToolDispatcher.cs @@ -11,7 +11,7 @@ public sealed class InternalToolDispatcher(IToolPolicyEngine policy, IInternalTo { InternalToolValidator.Validate(toolName, arguments); ToolPolicyDecision decision = policy.Evaluate(toolName, arguments); - if (!decision.Allowed) return new(false, decision.Reason, false, $"policy:{toolName}:{decision.Reason}"); + if (!decision.Allowed) return new(false, decision.Reason, false, $"policy:{toolName}:{decision.Reason}", RetryAllowed: false); return await backend.ExecuteAsync(taskId, toolName, arguments, cancellationToken).ConfigureAwait(false); } } diff --git a/src/Agent.Core/Tools/ToolPolicy.cs b/src/Agent.Core/Tools/ToolPolicy.cs index c9f216a..d478a2c 100644 --- a/src/Agent.Core/Tools/ToolPolicy.cs +++ b/src/Agent.Core/Tools/ToolPolicy.cs @@ -20,7 +20,12 @@ public interface IInternalToolBackend Task EndTaskAsync(Guid taskId, bool success, CancellationToken cancellationToken) => Task.CompletedTask; } -public sealed record ToolExecutionResult(bool Success, string Output, bool ExternalEffect, string? FailureFingerprint = null); +public sealed record ToolExecutionResult( + bool Success, + string Output, + bool ExternalEffect, + string? FailureFingerprint = null, + bool RetryAllowed = true); public sealed class DenyByDefaultPolicy(IReadOnlySet<string>? allowedTools = null) : IToolPolicyEngine { |
