diff --git a/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/session/AIAgentLLMSession.kt b/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/session/AIAgentLLMSession.kt index 60b5509870..7664a15273 100644 --- a/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/session/AIAgentLLMSession.kt +++ b/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/session/AIAgentLLMSession.kt @@ -230,7 +230,7 @@ public sealed class AIAgentLLMSession( fixingModel: LLModel = OpenAIModels.Chat.GPT4o ): Result> { validateSession() - val preparedPrompt = preparePrompt(prompt, tools) + val preparedPrompt = preparePrompt(prompt, tools = emptyList()) return executor.executeStructured(preparedPrompt, model, structure, retries, fixingModel) } @@ -242,7 +242,7 @@ public sealed class AIAgentLLMSession( */ public open suspend fun requestLLMStructuredOneShot(structure: StructuredData): StructuredResponse { validateSession() - val preparedPrompt = preparePrompt(prompt, tools) + val preparedPrompt = preparePrompt(prompt, tools = emptyList()) return executor.executeStructuredOneShot(preparedPrompt, model, structure) } diff --git a/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/environment/SafeTool.kt b/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/environment/SafeTool.kt index 745217fa93..64c2b337d4 100644 --- a/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/environment/SafeTool.kt +++ b/agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/environment/SafeTool.kt @@ -62,9 +62,13 @@ public data class SafeTool( * Casts the current instance of `Result` to a `Success` type if it is a successful result. * * @return The current instance cast to `Success`. - * @throws ClassCastException If the current instance is not of type `Success`. + * @throws IllegalStateException if not [Success] */ - public fun asSuccessful(): Success = this as Success + public fun asSuccessful(): Success = when (this) { + is Success -> this + is Failure -> throw IllegalStateException("Result is not a success: $this") + } + /** * Casts the current object to a `Failure` type. * @@ -72,9 +76,12 @@ public data class SafeTool( * Use it to retrieve the object as a `Failure` and access its specific properties and behaviors. * * @return The current instance cast to `Failure`. - * @throws ClassCastException if the current instance is not of type `Failure`. + * @throws IllegalStateException if not [Failure] */ - public fun asFailure(): Failure = this as Failure + public fun asFailure(): Failure = when (this) { + is Success -> throw IllegalStateException("Result is not a failure: $this") + is Failure -> this + } /** * Represents a successful result of an operation, wrapping a specific tool result and its corresponding content. diff --git a/agents/agents-ext/src/commonMain/kotlin/ai/koog/agents/ext/agent/AIAgentSubgraphExt.kt b/agents/agents-ext/src/commonMain/kotlin/ai/koog/agents/ext/agent/AIAgentSubgraphExt.kt index 4461b24ec3..0fd34e2786 100644 --- a/agents/agents-ext/src/commonMain/kotlin/ai/koog/agents/ext/agent/AIAgentSubgraphExt.kt +++ b/agents/agents-ext/src/commonMain/kotlin/ai/koog/agents/ext/agent/AIAgentSubgraphExt.kt @@ -7,7 +7,9 @@ import ai.koog.agents.core.dsl.builder.AIAgentSubgraphBuilderBase import ai.koog.agents.core.dsl.builder.AIAgentSubgraphDelegateBase import ai.koog.agents.core.dsl.builder.forwardTo import ai.koog.agents.core.dsl.extension.* +import ai.koog.agents.core.environment.ReceivedToolResult import ai.koog.agents.core.environment.SafeTool +import ai.koog.agents.core.environment.result import ai.koog.agents.core.environment.toSafeResult import ai.koog.agents.core.tools.* import ai.koog.prompt.llm.LLModel @@ -218,8 +220,15 @@ public fun AIAgentSubgraphBuilderBase<* defineTask(input) } - val finalizeTask by node { input -> + val finalizeTask by node { input -> llm.writeSession { + // Append final tool call result to the prompt for further LLM calls to see it (otherwise they would fail) + updatePrompt { + tool { + result(input) + } + } + // Remove finish tool from tools tools = tools - finishTool.descriptor @@ -228,7 +237,7 @@ public fun AIAgentSubgraphBuilderBase<* changeLLMParams(storage.getValue(origParamsKey)) } - input + input.toSafeResult().asSuccessful().result } // Helper node to overcome problems of the current api and repeat less code when writing routing conditions @@ -251,12 +260,7 @@ public fun AIAgentSubgraphBuilderBase<* } ) - edge( - callTool forwardTo finalizeTask - onCondition { it.tool == finishTool.name } - // result should always be successful, otherwise throw - transformed { it.toSafeResult().asSuccessful().result } - ) + edge(callTool forwardTo finalizeTask onCondition { it.tool == finishTool.name }) edge(callTool forwardTo sendToolResult) edge(sendToolResult forwardTo nodeDecide) diff --git a/prompt/prompt-model/src/commonMain/kotlin/ai/koog/prompt/dsl/PromptBuilder.kt b/prompt/prompt-model/src/commonMain/kotlin/ai/koog/prompt/dsl/PromptBuilder.kt index d28f4acfc5..020ca0a601 100644 --- a/prompt/prompt-model/src/commonMain/kotlin/ai/koog/prompt/dsl/PromptBuilder.kt +++ b/prompt/prompt-model/src/commonMain/kotlin/ai/koog/prompt/dsl/PromptBuilder.kt @@ -224,7 +224,6 @@ public class PromptBuilder internal constructor( * * @param call The tool call message to add */ - @Deprecated("Use call(id, tool, content) instead", ReplaceWith("call(id, tool, content)")) public fun call(call: Message.Tool.Call) { this@PromptBuilder.messages.add(call) } @@ -250,7 +249,6 @@ public class PromptBuilder internal constructor( * * @param result The tool result message to add */ - @Deprecated("Use result(id, tool, content) instead", ReplaceWith("result(id, tool, content)")) public fun result(result: Message.Tool.Result) { this@PromptBuilder.messages .indexOfLast { it is Message.Tool.Call && it.id == result.id }