Skip to content

Commit c10abf2

Browse files
committed
Rewrite all tools and examples with the new API
1 parent 1674aae commit c10abf2

File tree

49 files changed

+782
-1158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+782
-1158
lines changed

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

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import ai.koog.agents.core.agent.AIAgentTool.AgentToolArgs
44
import ai.koog.agents.core.agent.AIAgentTool.AgentToolResult
55
import ai.koog.agents.core.tools.Tool
66
import ai.koog.agents.core.tools.ToolDescriptor
7-
import ai.koog.agents.core.tools.ToolParameterDescriptor
7+
import ai.koog.agents.core.tools.annotations.InternalAgentToolsApi
8+
import ai.koog.agents.core.tools.asToolDescriptor
89
import kotlinx.serialization.KSerializer
910
import kotlinx.serialization.Serializable
1011
import kotlinx.serialization.descriptors.SerialDescriptor
@@ -20,7 +21,9 @@ import kotlinx.serialization.serializer
2021
*
2122
* @param agentName Agent name that would be a tool name for this agent tool.
2223
* @param agentDescription Agent description that would be a tool description for this agent tool.
23-
* @param inputDescriptor Descriptor for the agent input.
24+
* @param inputDescription An optional description of the agent's input. Required for primitive types only!
25+
* * If not specified for a primitive input type (ex: String, Int, ...), an empty input description will be sent to LLM.
26+
* * Does not have any effect for non-primitive [Input] type with @LLMDescription annotations.
2427
* @param inputSerializer Serializer to deserialize tool arguments to agent input.
2528
* @param outputSerializer Serializer to serialize agent output to tool result.
2629
* @param json Optional [Json] instance to customize de/serialization behavior.
@@ -29,38 +32,43 @@ import kotlinx.serialization.serializer
2932
public inline fun <reified Input, reified Output> AIAgent<Input, Output>.asTool(
3033
agentName: String,
3134
agentDescription: String,
32-
inputDescriptor: ToolParameterDescriptor,
35+
inputDescription: String? = null,
3336
inputSerializer: KSerializer<Input> = serializer(),
3437
outputSerializer: KSerializer<Output> = serializer(),
3538
json: Json = Json.Default,
3639
): Tool<AgentToolArgs, AgentToolResult> = AIAgentTool(
3740
agent = this,
3841
agentName = agentName,
3942
agentDescription = agentDescription,
40-
inputDescriptor = inputDescriptor,
43+
inputDescription = inputDescription,
4144
inputSerializer = inputSerializer,
4245
outputSerializer = outputSerializer,
4346
json = json,
4447
)
4548

49+
4650
/**
47-
* AIAgentTool is a specialized tool that integrates an AI agent for processing tasks
48-
* by leveraging input arguments and producing corresponding results.
49-
*
50-
* This class extends the generic Tool interface with custom argument and result types.
51-
*
52-
* @constructor Creates an instance of AIAgentTool with the specified AI agent, its name,
53-
* description, and an optional description for the request parameter.
51+
* AIAgentTool is a generic tool that wraps an AI agent to facilitate integration
52+
* with the context of a tool execution framework. It enables the serialization,
53+
* deserialization, and execution of an AI agent's operations.
5454
*
55-
* @param agent The AI agent that implements the AIAgentBase interface and handles task execution.
56-
* @param agentName A name assigned to the tool that helps identify it.
57-
* @param agentDescription A brief description of what the tool does.
55+
* @param Input The type of input expected by the AI agent.
56+
* @param Output The type of output produced by the AI agent.
57+
* @property agent The AI agent to be executed.
58+
* @property agentName A unique name for the agent.
59+
* @property agentDescription A brief description of the agent's functionality.
60+
* @property inputDescription An optional description of the agent's input. Required for primitive types only!
61+
* If not specified for a primitive input type (ex: String, Int, ...), an empty input description will be sent to LLM.
62+
* Does not have any effect for non-primitive [Input] type with @LLMDescription annotations.
63+
* @property inputSerializer A serializer for converting the input type to/from JSON.
64+
* @property outputSerializer A serializer for converting the output type to/from JSON.
65+
* @property json The JSON configuration used for serialization and deserialization.
5866
*/
5967
public class AIAgentTool<Input, Output>(
6068
private val agent: AIAgent<Input, Output>,
6169
private val agentName: String,
6270
private val agentDescription: String,
63-
private val inputDescriptor: ToolParameterDescriptor,
71+
private val inputDescription: String? = null,
6472
private val inputSerializer: KSerializer<Input>,
6573
private val outputSerializer: KSerializer<Output>,
6674
private val json: Json = Json.Default,
@@ -104,15 +112,19 @@ public class AIAgentTool<Input, Output>(
104112
}
105113
}
106114

107-
override val descriptor: ToolDescriptor = ToolDescriptor(
108-
name = agentName,
109-
description = agentDescription,
110-
requiredParameters = listOf(inputDescriptor)
111-
)
115+
override val name: String = agentName
116+
override val toolDescription: String = agentDescription
117+
118+
@OptIn(InternalAgentToolsApi::class)
119+
override val descriptor: ToolDescriptor =
120+
inputSerializer.descriptor.asToolDescriptor(name, toolDescription, inputDescription)
112121

113122
override suspend fun execute(args: AgentToolArgs): AgentToolResult {
114123
return try {
115-
val input = json.decodeFromJsonElement(inputSerializer, args.args.getValue(inputDescriptor.name))
124+
val input = json.decodeFromJsonElement(
125+
inputSerializer,
126+
args.args.getValue(descriptor.requiredParameters.first().name)
127+
)
116128
val result = agent.run(input)
117129

118130
AgentToolResult(
@@ -122,9 +134,11 @@ public class AIAgentTool<Input, Output>(
122134
} catch (e: Throwable) {
123135
AgentToolResult(
124136
successful = false,
125-
errorMessage = "Error happened: ${e::class.simpleName}(${e.message})\n${e.stackTraceToString().take(
126-
100
127-
)}"
137+
errorMessage = "Error happened: ${e::class.simpleName}(${e.message})\n${
138+
e.stackTraceToString().take(
139+
100
140+
)
141+
}"
128142
)
129143
}
130144
}

agents/agents-core/src/commonTest/kotlin/ai/koog/agents/core/CalculatorTools.kt

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,36 @@
11
package ai.koog.agents.core
22

33
import ai.koog.agents.core.tools.Tool
4-
import ai.koog.agents.core.tools.ToolDescriptor
5-
import ai.koog.agents.core.tools.ToolParameterDescriptor
6-
import ai.koog.agents.core.tools.ToolParameterType
4+
import ai.koog.agents.core.tools.annotations.LLMDescription
75
import kotlinx.serialization.KSerializer
86
import kotlinx.serialization.Serializable
9-
import kotlinx.serialization.builtins.serializer
107
import kotlin.jvm.JvmInline
118

129
object CalculatorTools {
1310

1411
abstract class CalculatorTool(
15-
name: String,
16-
description: String,
12+
override val name: String,
13+
override val toolDescription: String,
1714
) : Tool<CalculatorTool.Args, CalculatorTool.Result>() {
1815
@Serializable
19-
data class Args(val a: Float, val b: Float)
16+
data class Args(
17+
@property:LLMDescription("First number")
18+
val a: Float,
19+
@property:LLMDescription("Second number")
20+
val b: Float
21+
)
2022

2123
@Serializable
2224
@JvmInline
2325
value class Result(val result: Float)
2426

2527
final override val argsSerializer = Args.serializer()
2628
override val resultSerializer: KSerializer<Result> = Result.serializer()
27-
28-
final override val descriptor = ToolDescriptor(
29-
name = name,
30-
description = description,
31-
requiredParameters = listOf(
32-
ToolParameterDescriptor(
33-
name = "a",
34-
description = "First number",
35-
type = ToolParameterType.Float,
36-
),
37-
ToolParameterDescriptor(
38-
name = "b",
39-
description = "Second number",
40-
type = ToolParameterType.Float,
41-
),
42-
)
43-
)
4429
}
4530

4631
object PlusTool : CalculatorTool(
4732
name = "plus",
48-
description = "Adds a and b",
33+
toolDescription = "Adds a and b",
4934
) {
5035
override suspend fun execute(args: Args): Result {
5136
return Result(args.a + args.b)

agents/agents-core/src/commonTest/kotlin/ai/koog/agents/core/agent/AIAgentToolTest.kt

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package ai.koog.agents.core.agent
33
import ai.koog.agents.core.agent.config.AIAgentConfig
44
import ai.koog.agents.core.agent.config.AIAgentConfigBase
55
import ai.koog.agents.core.tools.DirectToolCallsEnabler
6-
import ai.koog.agents.core.tools.ToolParameterDescriptor
76
import ai.koog.agents.core.tools.ToolParameterType
87
import ai.koog.agents.core.tools.annotations.InternalAgentToolsApi
98
import ai.koog.prompt.dsl.prompt
@@ -54,11 +53,7 @@ class AIAgentToolTest {
5453
val tool = agent.asTool(
5554
agentName = "testAgent",
5655
agentDescription = "Test agent description",
57-
inputDescriptor = ToolParameterDescriptor(
58-
name = "request",
59-
description = "Test request description",
60-
type = ToolParameterType.String
61-
)
56+
inputDescription = "Test request description"
6257
)
6358

6459
val argsJson = buildJsonObject {
@@ -71,11 +66,7 @@ class AIAgentToolTest {
7166
val tool = agent.asTool(
7267
agentName = "testAgent",
7368
agentDescription = "Test agent description",
74-
inputDescriptor = ToolParameterDescriptor(
75-
name = "request",
76-
description = "Test request description",
77-
type = ToolParameterType.String
78-
)
69+
inputDescription = "Test request description"
7970
)
8071

8172
assertEquals("testAgent", tool.descriptor.name)
@@ -91,11 +82,7 @@ class AIAgentToolTest {
9182
val tool = agent.asTool(
9283
agentName = "testAgent",
9384
agentDescription = "Test agent description",
94-
inputDescriptor = ToolParameterDescriptor(
95-
name = "request",
96-
description = "Test request description",
97-
type = ToolParameterType.String
98-
)
85+
inputDescription = "Test request description"
9986
)
10087
assertEquals("testAgent", tool.descriptor.name)
10188
}
@@ -139,11 +126,7 @@ class AIAgentToolTest {
139126
val tool = agent.asTool(
140127
agentName = "testAgent",
141128
agentDescription = "Test agent description",
142-
inputDescriptor = ToolParameterDescriptor(
143-
name = "request",
144-
description = "Test request description",
145-
type = ToolParameterType.String
146-
)
129+
inputDescription = "Test request description"
147130
)
148131

149132
val args = tool.decodeArgs(argsJson)
@@ -164,11 +147,7 @@ class AIAgentToolTest {
164147
val tool = agent.asTool(
165148
agentName = "testAgent",
166149
agentDescription = "Test agent description",
167-
inputDescriptor = ToolParameterDescriptor(
168-
name = "request",
169-
description = "Test request description",
170-
type = ToolParameterType.String
171-
)
150+
inputDescription = "Test request description"
172151
)
173152

174153
val args = tool.decodeArgs(argsJson)

agents/agents-core/src/commonTest/kotlin/ai/koog/agents/core/agent/DummyTools.kt

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,29 @@ import ai.koog.agents.core.tools.SimpleTool
44
import ai.koog.agents.core.tools.ToolDescriptor
55
import ai.koog.agents.core.tools.ToolParameterDescriptor
66
import ai.koog.agents.core.tools.ToolParameterType
7+
import ai.koog.agents.core.tools.annotations.LLMDescription
78
import kotlinx.serialization.Serializable
89
import kotlinx.serialization.builtins.serializer
910

1011
object DummyTool : SimpleTool<Unit>() {
1112
override val argsSerializer = Unit.serializer()
1213

13-
override val descriptor = ToolDescriptor(
14-
name = "dummy",
15-
description = "Dummy tool for testing",
16-
requiredParameters = emptyList()
17-
)
14+
override val name: String = "dummy"
15+
override val toolDescription: String = "Dummy tool for testing"
1816

1917
override suspend fun doExecute(args: Unit): String = "Dummy result"
2018
}
2119

2220
object CreateTool : SimpleTool<CreateTool.Args>() {
2321
@Serializable
24-
data class Args(val name: String)
22+
data class Args(
23+
@property:LLMDescription("Name of the entity to create") val name: String
24+
)
2525

2626
override val argsSerializer = Args.serializer()
2727

28-
override val descriptor = ToolDescriptor(
29-
name = "create",
30-
description = "Create something",
31-
requiredParameters = listOf(
32-
ToolParameterDescriptor(
33-
name = "name",
34-
description = "Name of the entity to create",
35-
type = ToolParameterType.String
36-
)
37-
)
38-
)
28+
override val name: String = "create"
29+
override val toolDescription: String = "Create something"
3930

4031
override suspend fun doExecute(args: Args): String = "created"
4132
}

agents/agents-core/src/commonTest/kotlin/ai/koog/agents/core/agent/context/AIAgentLLMContextTest.kt

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ai.koog.agents.core.tools.ToolDescriptor
66
import ai.koog.agents.core.tools.ToolParameterDescriptor
77
import ai.koog.agents.core.tools.ToolParameterType
88
import ai.koog.agents.core.tools.ToolRegistry
9+
import ai.koog.agents.core.tools.annotations.LLMDescription
910
import ai.koog.agents.testing.tools.getMockExecutor
1011
import ai.koog.agents.testing.tools.mockLLMAnswer
1112
import ai.koog.prompt.dsl.prompt
@@ -171,22 +172,16 @@ class AIAgentLLMContextTest : AgentTestBase() {
171172
}
172173

173174
@Serializable
174-
private data class TestToolArgs(val input: String)
175+
private data class TestToolArgs(
176+
@property:LLMDescription("The input to process")
177+
val input: String
178+
)
175179

176180
private class TestTool : SimpleTool<TestToolArgs>() {
177181
override val argsSerializer = TestToolArgs.serializer()
178182

179-
override val descriptor = ToolDescriptor(
180-
name = "test-tool",
181-
description = "A test tool for testing",
182-
requiredParameters = listOf(
183-
ToolParameterDescriptor(
184-
name = "input",
185-
description = "The input to process",
186-
type = ToolParameterType.String
187-
)
188-
)
189-
)
183+
override val name: String = "test-tool"
184+
override val toolDescription: String = "A test tool for testing"
190185

191186
override suspend fun doExecute(args: TestToolArgs): String {
192187
return "Processed: ${args.input}"

agents/agents-core/src/commonTest/kotlin/ai/koog/agents/core/agent/session/AIAgentLLMWriteSessionTest.kt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ai.koog.agents.core.tools.ToolParameterType
1313
import ai.koog.agents.core.tools.ToolRegistry
1414
import ai.koog.agents.core.tools.ToolResult
1515
import ai.koog.agents.core.tools.annotations.InternalAgentToolsApi
16+
import ai.koog.agents.core.tools.annotations.LLMDescription
1617
import ai.koog.agents.testing.tools.getMockExecutor
1718
import ai.koog.agents.testing.tools.mockLLMAnswer
1819
import ai.koog.prompt.dsl.Prompt
@@ -64,21 +65,15 @@ class AIAgentLLMWriteSessionTest {
6465

6566
class TestTool : SimpleTool<TestTool.Args>() {
6667
@Serializable
67-
data class Args(val input: String)
68+
data class Args(
69+
@property:LLMDescription("Input parameter")
70+
val input: String
71+
)
6872

6973
override val argsSerializer: KSerializer<Args> = Args.serializer()
7074

71-
override val descriptor: ToolDescriptor = ToolDescriptor(
72-
name = "test-tool",
73-
description = "A test tool",
74-
requiredParameters = listOf(
75-
ToolParameterDescriptor(
76-
name = "input",
77-
description = "Input parameter",
78-
type = ToolParameterType.String
79-
)
80-
)
81-
)
75+
override val name: String = "test-tool"
76+
override val toolDescription: String = "A test tool"
8277

8378
override suspend fun doExecute(args: Args): String {
8479
return "Processed: ${args.input}"
@@ -90,11 +85,17 @@ class AIAgentLLMWriteSessionTest {
9085
data class Args(val input: String)
9186

9287
@Serializable
93-
data class Result(val output: String)
88+
data class Result(
89+
@property:LLMDescription("Input parameter")
90+
val output: String
91+
)
9492

9593
override val argsSerializer: KSerializer<Args> = Args.serializer()
9694
override val resultSerializer: KSerializer<Result> = Result.serializer()
9795

96+
override val name: String = "custom-tool"
97+
override val toolDescription: String = "A custom tool"
98+
9899
override val descriptor: ToolDescriptor = ToolDescriptor(
99100
name = "custom-tool",
100101
description = "A custom tool",

0 commit comments

Comments
 (0)