KEMBAR78
Get rid of required `finishTool` and support tools as functions in `subgraphWithTask`, deprecate `ToolArgs` and `ToolResult`, auto-generate `ToolDescriptor` by Ololoshechkin · Pull Request #791 · JetBrains/koog · GitHub
Skip to content

Conversation

Ololoshechkin
Copy link
Collaborator

@Ololoshechkin Ololoshechkin commented Sep 12, 2025

  1. Automatic Tool Descriptor Generation
  • Tool descriptors no longer need to be written manually — they are generated automatically.
  • Tool parameters must be annotated with @LLMDescription to provide descriptions.
  1. subgraphWithTask ыimplification (no longer requires finishTool, deduces all information by output type automatically)

  2. Serialization Improvements

  • ToolArgs and ToolResult are no longer needed — everything is handled via serialization.
  • ToolResult is now always Serializable to Json
  • For rare cases where JSON is not applicable:
    • Inherit from ToolResult.TextSerializable and implement fun textForLLM().
    • Specify resultSerializer = ToolResultUtils.toTextSerializer().
    • The LLM will then receive the output from textForLLM().
  1. Agent.asTool() no longer requires a ToolDescriptor.
    (Requires only toolDescription: String, and only if the agent’s input type is a primitive (e.g., String). If the input type is not primitive, descriptions are taken from @LLMDescription.)

Type of the changes

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tests improvement
  • Refactoring

Checklist

  • The pull request has a description of the proposed change
  • I read the Contributing Guidelines before opening the pull request
  • The pull request uses develop as the base branch
  • Tests for the changes have been added
  • All new and existing tests passed
Additional steps for pull requests adding a new feature
  • An issue describing the proposed change exists
  • The pull request includes a link to the issue
  • The change was discussed and approved in the issue
  • Docs have been added / updated

@Ololoshechkin Ololoshechkin force-pushed the vbr/subgraph-with-task-fix branch 2 times, most recently from b8968c9 to c10abf2 Compare September 15, 2025 14:22
@Ololoshechkin Ololoshechkin changed the title Get rid of required finishTool and support tools as functions in subgraphWithTask, deprecate ToolArgs and ToolResult Get rid of required finishTool and support tools as functions in subgraphWithTask, deprecate ToolArgs and ToolResult, auto-generate ToolDescriptor Sep 15, 2025
@aozherelyeva aozherelyeva force-pushed the vbr/subgraph-with-task-fix branch from ed46f91 to a03f1b7 Compare September 16, 2025 13:16
@github-actions
Copy link

github-actions bot commented Sep 17, 2025

Qodana for JVM

848 new problems were found

Inspection name Severity Problems
Check Kotlin and Java source code coverage 🔶 Warning 829
Vulnerable imported dependency 🔶 Warning 17
Unused import directive 🔶 Warning 1
Missing KDoc for public API declaration 🔶 Warning 1
@@ Code coverage @@
+ 69% total lines covered
12404 lines analyzed, 8647 lines covered
# Calculated according to the filters of your coverage tool

☁️ View the detailed Qodana report

Contact Qodana team

Contact us at qodana-support@jetbrains.com

Copy link
Collaborator

@tiginamaria tiginamaria left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much nicer than it was!

It seems like not you can not provide a argument description for the primitive typed argument, or I miss something?

internal class PrimitiveTool(name: String) : Tool<Int, String>() {
    override val name = "primitive_tool"

    override val argsSerializer = Int.serializer()
    override val resultSerializer = String.serializer()
    
    override val toolDescription: String = "First tool description"

    override suspend fun execute(args: Int): String = "Do nothing $args"
}

Also, I'd add more tests for such cases (for example how List of not primitive type will work and other unusual cases)

@sdubov
Copy link
Contributor

sdubov commented Sep 23, 2025

I like the simplified API. I have some small comments related to this change. Overall looks good for me.

@sdubov
Copy link
Contributor

sdubov commented Sep 23, 2025

It seems like not you can not provide a argument description for the primitive typed argument, or I miss something?

internal class PrimitiveTool(name: String) : Tool<Int, String>() {
    override val name = "primitive_tool"

    override val argsSerializer = Int.serializer()
    override val resultSerializer = String.serializer()
    
    override val toolDescription: String = "First tool description"

    override suspend fun execute(args: Int): String = "Do nothing $args"
}

Also, I'd add more tests for such cases (for example how List of not primitive type will work and other unusual cases)

If I correctly understand the new API, you need to do it through:

internal data class Args(
        @property:LLMDescription("Number to convert to string")
        val number: Int
)

It would be nice if we can use a primitive types though.

@tiginamaria tiginamaria self-requested a review September 23, 2025 11:52
Copy link
Collaborator

@tiginamaria tiginamaria left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think not having args description for primitive types is not a blocker at all:

  1. You can just describe the argument in tool description string
  2. You can override tool description and define the proper schema
  3. You can always use data class Args(value: Int) with @property:LLMDescription
  4. Case with primitive input + tool as a class definition is super rear (only multiplatform I guess, but maybe it's better to work on cross-platform annotations or some other ways of supporting tools as function there)

@Ololoshechkin Ololoshechkin force-pushed the vbr/subgraph-with-task-fix branch from f0503d7 to 803171e Compare September 26, 2025 02:05
nomisRev and others added 15 commits September 26, 2025 15:15
Refactor `SerialToToolDescription` by extracting `parameterDescriptors` helper method to improve code reuse and clarity.

Add comprehensive tests for `SerialDescriptor` to `ToolDescription` mapping and improve utility method structure.

- Added unit tests in `LLMDescriptionUsageTest` and `SerialToToolDescriptionTest` to validate `SerialDescriptor` to `ToolDescriptor` conversions, covering edge cases and annotations.
- Extracted private helper `description()` to streamline annotation description retrieval.
- Improved parameter handling by introducing local variables for clarity and consistency.

Refactor SimpleTool.kt to work with String instead of ToolResult.Text

KtLint: Fix import order

Remove unrelated change

Introduce KMP support for deriving ToolDescription based on SerialDescriptor.

Deprecate `ToolResult` and refactor tools to use KotlinX Serialization for results.

Deprecate ToolArgs.kt, and remove usage.
…alizable abstract class for custom serialization of tool results as text/markdown
@Ololoshechkin Ololoshechkin force-pushed the vbr/subgraph-with-task-fix branch from 3e21c19 to 748d07f Compare September 26, 2025 13:19
@Ololoshechkin Ololoshechkin merged commit c433b8e into develop Sep 26, 2025
15 checks passed
@Ololoshechkin Ololoshechkin deleted the vbr/subgraph-with-task-fix branch September 26, 2025 14:47
aozherelyeva added a commit that referenced this pull request Oct 1, 2025
…ations (#889)

<!--
Thank you for opening a pull request!

Please add a brief description of the proposed change here.
Also, please tick the appropriate points in the checklist below.
-->

## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
As a follow-up to our last week discussion, it's good to test different
input/output combinations in tool descriptors after the merge of #791.

## Breaking Changes
<!-- Will users need to update their code or configurations? -->
None.
---

#### Type of the changes
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Tests improvement
- [ ] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [x] An issue describing the proposed change exists
- [x] The pull request includes a link to the issue
- [x] The change was discussed and approved in the issue
- [ ] Docs have been added / updated
nicolasf added a commit to nicolasf/koog that referenced this pull request Oct 1, 2025
Fixes @tool("customName") not working after JetBrains#791.
Ololoshechkin pushed a commit that referenced this pull request Oct 2, 2025
…ations (#889)

<!--
Thank you for opening a pull request!

Please add a brief description of the proposed change here.
Also, please tick the appropriate points in the checklist below.
-->

## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
As a follow-up to our last week discussion, it's good to test different
input/output combinations in tool descriptors after the merge of #791.

## Breaking Changes
<!-- Will users need to update their code or configurations? -->
None.
---

#### Type of the changes
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Tests improvement
- [ ] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [x] An issue describing the proposed change exists
- [x] The pull request includes a link to the issue
- [x] The change was discussed and approved in the issue
- [ ] Docs have been added / updated

(cherry picked from commit 58ba445)
nicolasf added a commit to nicolasf/koog that referenced this pull request Oct 3, 2025
Fixes @tool("customName") not working after JetBrains#791.
nicolasf added a commit to nicolasf/koog that referenced this pull request Oct 3, 2025
Fixes @tool("customName") not working after JetBrains#791.
karloti pushed a commit to karloti/koog that referenced this pull request Oct 21, 2025
…ubgraphWithTask`, deprecate `ToolArgs` and `ToolResult`, make `ToolDescriptor` auto-generated for class-based tools (JetBrains#791)

1. Automatic Tool Descriptor Generation
- Tool descriptors no longer need to be written manually — they are
generated automatically.
- Tool parameters must be annotated with @LLMDescription to provide
descriptions.

2. subgraphWithTask ыimplification (no longer requires finishTool,
deduces all information by output type automatically)

3. Serialization Improvements
- ToolArgs and ToolResult are no longer needed — everything is handled
via serialization.
- ToolResult is now always Serializable to Json
- For rare cases where JSON is not applicable: 
- Inherit from ToolResult.TextSerializable and implement fun
textForLLM().
    - Specify resultSerializer = ToolResultUtils.toTextSerializer().
    - The LLM will then receive the output from textForLLM().

4. Agent.asTool() no longer requires a ToolDescriptor.
(Requires only toolDescription: String, and only if the agent’s input
type is a primitive (e.g., String). If the input type is not primitive,
descriptions are taken from @LLMDescription.)

---

#### Type of the changes
- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update
- [x] Tests improvement
- [x] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [ ] An issue describing the proposed change exists
- [ ] The pull request includes a link to the issue
- [ ] The change was discussed and approved in the issue
- [x] Docs have been added / updated

---------

Co-authored-by: Simon Vergauwen <nomisRev@users.noreply.github.com>
Co-authored-by: Anastasiia.Zarechneva <Anastasiia.Zarechneva@jetbrains.com>
karloti pushed a commit to karloti/koog that referenced this pull request Oct 21, 2025
…ations (JetBrains#889)

<!--
Thank you for opening a pull request!

Please add a brief description of the proposed change here.
Also, please tick the appropriate points in the checklist below.
-->

## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
As a follow-up to our last week discussion, it's good to test different
input/output combinations in tool descriptors after the merge of JetBrains#791.

## Breaking Changes
<!-- Will users need to update their code or configurations? -->
None.
---

#### Type of the changes
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Tests improvement
- [ ] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [x] An issue describing the proposed change exists
- [x] The pull request includes a link to the issue
- [x] The change was discussed and approved in the issue
- [ ] Docs have been added / updated

(cherry picked from commit 58ba445)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants