summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Agent.App/Logging/JsonLinesRuntimeObserver.cs2
-rw-r--r--src/Agent.Core/Runtime/AgentRuntime.cs8
-rw-r--r--src/Agent.Core/Tools/InternalToolDispatcher.cs2
-rw-r--r--src/Agent.Core/Tools/ToolPolicy.cs7
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
{