Skip to content

Commit 96f3897

Browse files
committed
Fix tests, linter, and doc knit
1 parent 503a41a commit 96f3897

File tree

9 files changed

+101
-26
lines changed

9 files changed

+101
-26
lines changed

agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/AIAgentTool.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ public inline fun <reified Input, reified Output> AIAgent<Input, Output>.asTool(
4646
json = json,
4747
)
4848

49-
5049
/**
5150
* AIAgentTool is a generic tool that wraps an AI agent to facilitate integration
5251
* with the context of a tool execution framework. It enables the serialization,

agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/environment/GenericAgentEnvironment.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ import ai.koog.agents.core.model.message.EnvironmentToolResultMultipleToAgentMes
1010
import ai.koog.agents.core.model.message.EnvironmentToolResultToAgentContent
1111
import ai.koog.agents.core.tools.DirectToolCallsEnabler
1212
import ai.koog.agents.core.tools.Tool
13-
import ai.koog.agents.core.tools.ToolArgs
1413
import ai.koog.agents.core.tools.ToolException
1514
import ai.koog.agents.core.tools.ToolRegistry
16-
import ai.koog.agents.core.tools.ToolResult
1715
import ai.koog.agents.core.tools.annotations.InternalAgentToolsApi
1816
import ai.koog.prompt.message.Message
1917
import io.github.oshai.kotlinlogging.KLogger

agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/model/message/Environment.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package ai.koog.agents.core.model.message
22

3-
43
/**
54
* Represents the content of tool result messages sent to an agent after a tool call is executed within
65
* the local environment. This provides the result of the tool execution alongside metadata such as

agents/agents-ext/src/commonMain/kotlin/ai/koog/agents/ext/tool/file/patch/TokenNormalizedPatchApplier.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ai.koog.agents.ext.tool.file.patch
22

3+
import kotlinx.serialization.Serializable
34
import kotlin.contracts.ExperimentalContracts
45
import kotlin.contracts.contract
56

@@ -29,21 +30,25 @@ internal fun applyTokenNormalizedPatch(content: String, patch: FilePatch): Patch
2930
/**
3031
* Represents the result of applying a patch to a file
3132
*/
33+
@Serializable
3234
public sealed interface PatchApplyResult {
3335

3436
/**
3537
* Represents a successful patch application
3638
*/
39+
@Serializable
3740
public data class Success(val updatedContent: String) : PatchApplyResult
3841

3942
/**
4043
* Represents a failed patch application, including the reason for the failure
4144
*/
45+
@Serializable
4246
public sealed class Failure(public val reason: String) : PatchApplyResult {
4347

4448
/**
4549
* Represents a failure to find the original text in the file content
4650
*/
51+
@Serializable
4752
public object OriginalNotFound : Failure(
4853
"""
4954
The original text to replace was not found in the file content.

agents/agents-tools/src/commonTest/kotlin/ai/koog/agents/core/tools/LLMDescriptionUsageTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class LLMDescriptionUsageTest {
3030
// All parameters use class-level description per current implementation
3131
val params = desc.requiredParameters + desc.optionalParameters
3232
assertEquals("a", params[0].description)
33-
assertEquals("b", params[0].description)
33+
assertEquals("b", params[1].description)
3434
}
3535

3636
// 2) Property-level LLMDescription does NOT override parameter descriptions currently

docs/docs/class-based-tools.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,82 @@ object CastToDoubleTool : SimpleTool<CastToDoubleTool.Args>() {
150150
```
151151
<!--- KNIT example-class-based-tools-02.kt -->
152152

153+
### Sending Tool Result to LLM in Custom Format
154+
155+
If you are not happy with JSON results sent to LLM (in some cases, LLMs can work better if tool output is structured as Markdown, for instance), you have to follow the following steps:
156+
1. Implement `ToolResult.TextSerializable` interface, and override `textForLLM()` method
157+
2. Override `resultSerializer` using `ToolResultUtils.toTextSerializer<T>()`
158+
159+
#### Example
160+
161+
<!--- INCLUDE
162+
import ai.koog.agents.core.tools.SimpleTool
163+
import ai.koog.agents.core.tools.ToolArgs
164+
import ai.koog.agents.core.tools.ToolDescriptor
165+
import ai.koog.agents.core.tools.ToolParameterDescriptor
166+
import ai.koog.agents.core.tools.ToolParameterType
167+
import kotlinx.serialization.Serializable
168+
import ai.koog.agents.core.tools.annotations.LLMDescription
169+
import ai.koog.prompt.markdown.markdown
170+
-->
171+
```kotlin
172+
// A tool that edits file
173+
object EditFile : Tool<EditFile.Args, EditFile.Result>() {
174+
// Define tool arguments
175+
@Serializable
176+
public data class Args(
177+
val path: String,
178+
val original: String,
179+
val replacement: String
180+
)
181+
182+
@Serializable
183+
public data class Result(
184+
private val patchApplyResult: PatchApplyResult
185+
) : ToolResult.TextSerializable() {
186+
187+
@Serializable
188+
public sealed interface PatchApplyResult {
189+
@Serializable
190+
public data class Success(val updatedContent: String) : PatchApplyResult
191+
192+
@Serializable
193+
public sealed class Failure(public val reason: String) : PatchApplyResult
194+
}
195+
196+
// Textual output (in Markdown format) that will be visible to the LLM after the tool finishes.
197+
override fun textForLLM(): String = markdown {
198+
if (patchApplyResult is PatchApplyResult.Success) {
199+
line {
200+
bold("Successfully").text(" edited file (patch applied)")
201+
}
202+
} else {
203+
line {
204+
text("File was ")
205+
.bold("not")
206+
.text(" modified (patch application failed: ${patchApplyResult.reason})")
207+
}
208+
}
209+
}
210+
211+
override fun toString(): String = textForLLM()
212+
}
213+
214+
// Serializer for the Args class
215+
override val argsSerializer = Args.serializer()
216+
217+
// Description of the tool, visible to LLM
218+
override val toolDescription = "Edits the given file"
219+
220+
// Function that executes the tool with the provided arguments
221+
override suspend fun execute(args: Args): Result {
222+
return TODO("Implement file edit")
223+
}
224+
}
225+
```
226+
<!--- KNIT example-class-based-tools-02.kt -->
227+
228+
229+
153230
After implementing your tool, you need to add it to a tool registry and then use it with an agent.
154231
For details, see [Tool registry](tools-overview.md#tool-registry).

docs/docs/testing.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public object AnalyzeTool : Tool<AnalyzeTool.Args, String>() {
133133
override val name = "message"
134134
override val toolDescription = "Service tool, used by the agent to talk with user"
135135
136-
override suspend fun execute(args: Args): String = args.message
136+
override suspend fun execute(args: Args): String = args.query
137137
}
138138
139139
typealias PositiveToneTool = SayToUser
@@ -430,10 +430,12 @@ object AnalyzeTool : Tool<AnalyzeTool.Args, String>() {
430430
@Serializable
431431
data class Args(
432432
@property:LLMDescription("Message from the agent")
433-
val query: String
433+
val query: String,
434+
val depth: Int
434435
)
435436
436437
override val argsSerializer: KSerializer<Args> = Args.serializer()
438+
override val resultSerializer: KSerializer<String> = String.serializer()
437439
438440
override val name = "message"
439441
override val toolDescription = "Service tool, used by the agent to talk with user"
@@ -499,7 +501,15 @@ object AnalyzeTool : Tool<AnalyzeTool.Args, AnalyzeTool.Result>() {
499501
val depth: Int
500502
)
501503
504+
@Serializable
505+
data class Result(
506+
val analysis: String,
507+
val confidence: Double,
508+
val metadata: Map<String, String> = mapOf()
509+
)
510+
502511
override val argsSerializer: KSerializer<Args> = Args.serializer()
512+
override val resultSerializer: KSerializer<String> = Result.serializer()
503513
504514
override val name = "message"
505515
override val toolDescription = "Service tool, used by the agent to talk with user"

docs/docs/tools-overview.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,7 @@ val analysisAgent = AIAgent(
215215
val analysisAgentTool = analysisAgent.asTool(
216216
agentName = "analyzeTransactions",
217217
agentDescription = "Performs financial transaction analysis",
218-
inputDescriptor = ToolParameterDescriptor(
219-
name = "request",
220-
description = "Transaction analysis request",
221-
type = ToolParameterType.String
222-
)
218+
inputDescription = "Transaction analysis request",
223219
)
224220
```
225221
<!--- KNIT example-tools-overview-05.kt -->

examples/notebooks/Banking.ipynb

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -888,9 +888,8 @@
888888
},
889889
{
890890
"metadata": {
891-
"ExecuteTime": {
892-
"end_time": "2025-08-18T19:31:37.345301Z",
893-
"start_time": "2025-08-18T19:31:37.295809Z"
891+
"jupyter": {
892+
"is_executing": true
894893
}
895894
},
896895
"cell_type": "code",
@@ -910,31 +909,23 @@
910909
" transferAgent.asTool(\n",
911910
" agentName = \"transferMoney\",\n",
912911
" agentDescription = \"Transfers money and handles all related operations\",\n",
913-
" inputDescriptor = ToolParameterDescriptor(\n",
914-
" name = \"request\",\n",
915-
" description = \"Transfer request from the user\",\n",
916-
" type = ToolParameterType.String\n",
917-
" )\n",
912+
" inputDescription = \"Transfer request from the user\"\n",
918913
" )\n",
919914
" )\n",
920915
"\n",
921916
" tool(\n",
922917
" analysisAgent.asTool(\n",
923918
" agentName = \"analyzeTransactions\",\n",
924919
" agentDescription = \"Performs analytics on user transactions\",\n",
925-
" inputDescriptor = ToolParameterDescriptor(\n",
926-
" name = \"request\",\n",
927-
" description = \"Transaction analytics request\",\n",
928-
" type = ToolParameterType.String\n",
929-
" )\n",
920+
" inputDescription = \"Transaction analytics request\"\n",
930921
" )\n",
931922
" )\n",
932923
" },\n",
933924
" systemPrompt = \"$bankingAssistantSystemPrompt\\n$transactionAnalysisPrompt\"\n",
934925
")"
935926
],
936927
"outputs": [],
937-
"execution_count": 19
928+
"execution_count": null
938929
},
939930
{
940931
"metadata": {},

0 commit comments

Comments
 (0)