diff options
| -rw-r--r-- | doc/Design.md | 6 | ||||
| -rw-r--r-- | src/Agent.Core/Prompts/PromptComposer.cs | 21 | ||||
| -rw-r--r-- | src/Agent.Core/Runtime/AgentRuntime.cs | 2 | ||||
| -rw-r--r-- | tests/Agent.Core.Tests/PromptAndRuntimeTests.cs | 6 |
4 files changed, 32 insertions, 3 deletions
diff --git a/doc/Design.md b/doc/Design.md index f8f5d0b..a637e3b 100644 --- a/doc/Design.md +++ b/doc/Design.md @@ -399,7 +399,11 @@ AgentSession 5. Sandbox capability summary 6. current TaskGraph / current Task 7. previous Summary -8. recent Conversation / Execution Result +8. recent verified Execution Result +9. current Taskの`requires_external_effect`に基づく実行要件 +10. recent Conversation + +実行要件は、外部効果が必要なTaskでは文章上の宣言、計画、JSON例を実行済みと扱わず、対応するInternal Toolを直ちに呼び出すよう指示する。成功済みのread結果はExecution Resultから再利用し、不要な再読込を避けてwrite/processへ進む。外部効果が不要なTaskにはToolを強制しない。 ### 9.3 Summary policy `num_ctx`に対する利用率が設定閾値を超えたとき、古いConversation/Execution Resultを要約する。利用率 = latest `prompt_eval_count` / `num_ctx`(累積 InputTokens ではない)。既定閾値は80%とする。次は削除・曖昧化してはならない。 - 利用者が明示した制約 diff --git a/src/Agent.Core/Prompts/PromptComposer.cs b/src/Agent.Core/Prompts/PromptComposer.cs index 69b18f3..2899088 100644 --- a/src/Agent.Core/Prompts/PromptComposer.cs +++ b/src/Agent.Core/Prompts/PromptComposer.cs @@ -13,8 +13,10 @@ public sealed record PromptContext( string SandboxCapabilitySummary, string TaskGraphSummary, string PreviousSummary, + IReadOnlyList<ExecutionResult> ExecutionResults, IReadOnlyList<ConversationMessage> Conversation, string Request, + bool RequiresExternalEffect, IReadOnlyList<string>? Images = null); public static class PromptComposer @@ -29,7 +31,9 @@ public static class PromptComposer new("system", ComposeSkillCatalog(context.AvailableSkills)), new("system", context.SandboxCapabilitySummary), new("system", context.TaskGraphSummary), - new("system", context.PreviousSummary) + new("system", context.PreviousSummary), + new("system", ComposeExecutionResults(context.ExecutionResults)), + new("system", ComposeExecutionRequirement(context.RequiresExternalEffect)) }; // Inject selected skill instructions (Progressive Disclosure Stage 3). foreach (AgentSkill skill in context.SelectedSkills) @@ -39,6 +43,21 @@ public static class PromptComposer return messages; } + private static string ComposeExecutionRequirement(bool requiresExternalEffect) => requiresExternalEffect + ? "The current Planner Task requires a verified external effect. Call the appropriate available Internal Tool now. " + + "A prose description, promise, plan, or fenced JSON example does not perform the operation and cannot complete this Task. " + + "After a successful read, use its returned content and proceed to the required write or process operation without repeating the read unnecessarily." + : "The current Planner Task does not require an external effect. Use an Internal Tool only when its verified result is needed; do not claim an unverified result."; + + private static string ComposeExecutionResults(IReadOnlyList<ExecutionResult> results) + { + if (results.Count == 0) return "No prior Execution Results are available for the current Session."; + var lines = new List<string> { "Recent verified Execution Results:" }; + foreach (ExecutionResult result in results) + lines.Add($"- {result.ToolName} ({(result.Success ? "success" : "failed")}): {result.Output}"); + return string.Join("\n", lines); + } + /// <summary> /// Stage 1 Discovery: only name + description are included. Full instructions are NOT included. /// </summary> diff --git a/src/Agent.Core/Runtime/AgentRuntime.cs b/src/Agent.Core/Runtime/AgentRuntime.cs index bc9fc5e..f1c7186 100644 --- a/src/Agent.Core/Runtime/AgentRuntime.cs +++ b/src/Agent.Core/Runtime/AgentRuntime.cs @@ -218,8 +218,10 @@ public sealed class AgentRuntime(TaskRegistry registry, IOllamaClient ollama, Ag settings.SandboxCapabilitySummary, BuildTaskGraphSummary(graph, plannerTask), session.Summary ?? string.Empty, + session.ExecutionResults, session.Conversation, plannerTask.Description, + plannerTask.RequiresExternalEffect, task.Images)).ToList(); var guard = new ToolUseGuard(settings.SameFailureLimit); diff --git a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs index 836ed5e..a40720f 100644 --- a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs +++ b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs @@ -20,12 +20,16 @@ public sealed class PromptAndRuntimeTests }; IReadOnlyList<OllamaMessage> messages = PromptComposer.Compose(new PromptContext( "fixed", "user system", "ja", availableSkills, [], "capability", "graph", "summary", + [new ExecutionResult(Guid.NewGuid(), "file_read", true, "verified content")], [new ConversationMessage("user", "old"), new ConversationMessage("assistant", "reply")], - "new request", ["image"])); + "new request", true, ["image"])); // Check that the skill catalog (name + description) is present, not the full instructions. Assert.Contains(messages, m => m.Content.Contains("test-skill") && m.Content.Contains("A test skill.")); Assert.DoesNotContain(messages, m => m.Content == "skill instructions"); + Assert.Contains(messages, m => m.Role == "system" && m.Content.Contains("requires a verified external effect", StringComparison.Ordinal)); + Assert.Contains(messages, m => m.Role == "system" && m.Content.Contains("fenced JSON example does not perform", StringComparison.Ordinal)); + Assert.Contains(messages, m => m.Role == "system" && m.Content.Contains("file_read (success): verified content", StringComparison.Ordinal)); Assert.Equal("system", messages[0].Role); Assert.Equal("user", messages[^1].Role); Assert.Equal(["image"], messages[^1].Images); |
