summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Agent.Core/Runtime/PlannerService.cs16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/Agent.Core/Runtime/PlannerService.cs b/src/Agent.Core/Runtime/PlannerService.cs
index b5ac80e..2a006f7 100644
--- a/src/Agent.Core/Runtime/PlannerService.cs
+++ b/src/Agent.Core/Runtime/PlannerService.cs
@@ -229,25 +229,34 @@ public sealed class PlannerService(IOllamaClient ollama, AgentRuntimeSettings se
Action<string, IReadOnlyList<OllamaMessage>, OllamaResult?, Exception?>? observeAttempt, Func<PlanResult, TaskGraph> buildGraph, CancellationToken cancellationToken)
{
Exception? firstFailure = null;
+ IReadOnlyList<OllamaMessage> attemptMessages = messages;
for (int attempt = 0; attempt < 2; attempt++)
{
OllamaResult? result = null;
try
{
bool? thinkOverride = attempt == 0 ? null : false;
- result = await _ollama.ChatStructuredAsync(messages, temperature, PlanSchema.Element, thinkOverride, cancellationToken).ConfigureAwait(false);
+ result = await _ollama.ChatStructuredAsync(attemptMessages, temperature, PlanSchema.Element, thinkOverride, cancellationToken).ConfigureAwait(false);
PlanResult? plan = ParsePlan(result.Content);
if (plan is null || plan.Tasks.Count == 0)
throw new PlannerValidationException("Ollama returned an empty or invalid structured plan.");
TaskGraph graph = buildGraph(plan);
- observeAttempt?.Invoke(phase, messages, result, null);
+ observeAttempt?.Invoke(phase, attemptMessages, result, null);
return graph;
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { throw; }
catch (Exception ex) when (ex is not (OutOfMemoryException or StackOverflowException or AccessViolationException))
{
- observeAttempt?.Invoke(phase, messages, result, ex);
+ observeAttempt?.Invoke(phase, attemptMessages, result, ex);
firstFailure ??= ex;
+ if (attempt == 0)
+ {
+ attemptMessages = messages.Concat([
+ new OllamaMessage("system",
+ "The previous response was not a valid TaskGraph JSON object. Do not call or execute any Tool while planning. " +
+ "Return only one JSON object that matches the supplied schema, beginning with {\"tasks\":[ and containing no Markdown or commentary.")
+ ]).ToArray();
+ }
}
}
throw new PlannerValidationException($"Structured {phase} failed after think=false retry: {firstFailure?.Message}");
@@ -294,6 +303,7 @@ public sealed class PlannerService(IOllamaClient ollama, AgentRuntimeSettings se
private static string BuildPlanningInstruction() =>
"""
You are a Task Planner. Decompose the user request into a TaskGraph of 1-32 tasks.
+ Planning is read-only: do not call or execute Tools. Return only one JSON object matching the supplied schema, with no Markdown or commentary.
Each task must have:
- description: a clear, self-contained sub-task description
- dependencies: array of task indices (0-based) that must complete before this task