Skip to content

feat(agents): Introduce wrapper for cli agents#1413

Open
antoniibelyshev wants to merge 19 commits into
developfrom
belyshev/cli-agents
Open

feat(agents): Introduce wrapper for cli agents#1413
antoniibelyshev wants to merge 19 commits into
developfrom
belyshev/cli-agents

Conversation

@antoniibelyshev
Copy link
Copy Markdown
Collaborator

@antoniibelyshev antoniibelyshev commented Jan 26, 2026

feat(CliAIAgent):
introduce CliAIAgent which calls another cli agent under the hood: e.g. claude, codex, etc.
CliAIAgent is an instance of AIAgent, and can also be used as a node in a graph, e.g. val claudeNode by ClaudeCodeAgent(...).asNode()

Motivation and Context

Breaking Changes


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
  • CI/CD changes
  • Dependencies update

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

@antoniibelyshev antoniibelyshev force-pushed the belyshev/cli-agents branch 4 times, most recently from 44e0012 to 3a801b4 Compare January 27, 2026 09:48
@antoniibelyshev antoniibelyshev changed the title WIP: write cli wrappers Wrappers for cli agents Jan 28, 2026
@antoniibelyshev antoniibelyshev changed the title Wrappers for cli agents Introduce wrapper for cli agents Jan 29, 2026
@antoniibelyshev antoniibelyshev changed the title Introduce wrapper for cli agents feat(agents): Introduce wrapper for cli agents Feb 16, 2026
Copy link
Copy Markdown
Collaborator

@Ololoshechkin Ololoshechkin left a comment

Choose a reason for hiding this comment

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

Please, add more tests on structured output, and see my other comments as well.

Additionally, please consider adding Java-friendly builder AIAgent.builder().agentConfig(...).cli(AIAgentCliStrategy. ...) ...
(add cli or cliStrategy in addition to .functionalStrategy, .goapStrategy and .graphStrategy).

Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
@Ololoshechkin
Copy link
Copy Markdown
Collaborator

AIAgentCliStrategy.claude<String, String>(
            "",
            transport = DockerCliTransport("image"),
            structure = JsonStructure.create<String>()
)

-- this part requires both <Input, Output> parameters as well as structure to define the Output.
Let's maybe make it consistent so that Input is also defined not via generic params but via some argument (KType or Class, etc.)

Also add Java test and check how it looks there :)

Copy link
Copy Markdown
Collaborator

@Ololoshechkin Ololoshechkin left a comment

Choose a reason for hiding this comment

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

also maybe we'd need to run integration tests for:

  • all types of CLI agents (codex, claude, ?)
  • all types of transport (docker, process)
  • all OS: mac, windows, linux

cc @aozherelyeva can you help please 🙏

Comment thread cli-transport/src/jvmCommonMain/kotlin/transport/ProcessCliTransport.kt Outdated
Comment thread cli-transport/src/jvmCommonMain/kotlin/transport/ProcessCliTransport.kt Outdated
Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
Comment thread agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/CliAIAgent.kt Outdated
Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
Comment thread cli-transport/src/jvmMain/kotlin/ai/koog/cli/transport/DockerCliTransport.kt Outdated
Comment thread agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/CliAIAgent.kt Outdated
@antoniibelyshev antoniibelyshev force-pushed the belyshev/cli-agents branch 8 times, most recently from 6562dad to 1f00287 Compare March 2, 2026 22:25
@antoniibelyshev antoniibelyshev force-pushed the belyshev/cli-agents branch 3 times, most recently from d4b0699 to d49ceb0 Compare March 31, 2026 08:26
Copy link
Copy Markdown
Collaborator

@sdubov sdubov left a comment

Choose a reason for hiding this comment

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

@antoniibelyshev, thank you for the fixed comments! I've added several more notes related to the code. Could you please check?

Comment thread cli-transport/src/jvmCommonMain/kotlin/transport/ProcessCliTransport.kt Outdated
Copy link
Copy Markdown
Collaborator

@sdubov sdubov left a comment

Choose a reason for hiding this comment

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

@antoniibelyshev , I have added several more question for the review. Could you please take a look.

The biggest concern from my side are:

  1. DummyPromptExecutor. It is quite unclear how will it work when somebody call the prompt executor. Maybe it worth adding a stubs that will delegate execution to the CLI agent in future and just blank for now

I will give an approve from my side to not block the merging, but I think it would be nice if someone from the team look on these changes as well. cc @EugeneTheDev, @Ololoshechkin

Could you please also check the documentation and Module.md file. It might worth add some examples in the md file.

Comment thread agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/AIAgent.kt Outdated
Comment thread agents/agents-core/src/commonMain/kotlin/ai/koog/agents/core/agent/CliAIAgent.kt Outdated
prompt = agentConfig.prompt,
model = agentConfig.model,
responseProcessor = agentConfig.responseProcessor,
promptExecutor = DummyPromptExecutor,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you please clarify this logic for me? Am I right that you replace the prompt executor here with a dummy instance and delegate the execution to the CLI process. If this is correct, I would like to clarify several questions:

  1. Do you expect to change the behaviour in future for better integration and interactions? For example, if I want to send some requests from Koog side inside a running CLI agent or respond to some questions received from CLI Agent?
  2. How would that work with features? Let's say I add a feature that use prompt executor. Will those calls all throw?
  3. Could you please add KDoc to the DummyPromptExecutor with some details if this is behaviour is not documented anywhere?

Comment thread cli-transport/src/commonMain/kotlin/ai/koog/cli/transport/CliEvent.kt Outdated
@sdubov sdubov self-requested a review May 5, 2026 09:28
Copy link
Copy Markdown
Collaborator

@EugeneTheDev EugeneTheDev left a comment

Choose a reason for hiding this comment

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

Please extract cli package from agents-core intro a separate module. We should avoid putting non-core stuff in core modules as much as possible

FROM node:20-slim

RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
RUN npm install -g @openai/codex @anthropic-ai/claude-code && npm cache clean --force
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please pin the exact version/hash when doing npm install, to prevent supply chain vulenrabilities

node-version: 20

- name: Install CLI agents globally
run: npm install -g @openai/codex @anthropic-ai/claude-code
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do you run npm install here, if the Dockerfile already has it? Seems like it's not needed here. And again, please always pin dependencies to exact versions/hashes

Copy link
Copy Markdown
Collaborator

@EugeneTheDev EugeneTheDev left a comment

Choose a reason for hiding this comment

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

Please also consider organizing agents cli package a bit. Currently, it has a flat structure, but I guess some of these classes can be grouped into several packages, for better readbility

/**
* Base class for cli-agent-related exceptions.
*/
public open class CliException(message: String, cause: Throwable? = null) : RuntimeException(message, cause)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is it a RuntimeException and not a regular Exception?

/**
* Interface for cli transport implementations.
*/
public expect interface CliTransport {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As far as I understand the use-case, this interface doesn't have to be expect/actual. You don't actually use it, the interface on both platforms looks the same. It's the platform-specific implementations that are located in platform-specific source sets anyway and contain platform-specific code. So you can make this one a regular interface

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The reason I made it expect/actual is that I wanted to have CliTransport.default(), CliTransport.withDocker, etc., but these are only available on jvm for now. Does this make sense or can I do it better?

/**
* Converts a JSON primitive to a string
*/
public val JsonElement.stringVal: String?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Putting extension functions/propeties inside objects/classes is usually a bad idea, if they're used outside of that specific scope, because it will be harder to discover and use them. Consider moving these to the top-level. Also, are these internal helpers or an actual public API? If it's the former, consider adding internal api annotation

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