Skip to content

refactor(agents): replace invoke constructors with factory methods#1882

Open
antoniibelyshev wants to merge 4 commits intodevelopfrom
belyshev/replace-invokes-with-factory-methods
Open

refactor(agents): replace invoke constructors with factory methods#1882
antoniibelyshev wants to merge 4 commits intodevelopfrom
belyshev/replace-invokes-with-factory-methods

Conversation

@antoniibelyshev
Copy link
Copy Markdown
Collaborator

Replaced the pattern

class A {
    companion object {
        operator fun invoke(...) = /* create an instance of A */
    }
}

with

class A { ... }
fun A(...) = /* create an instance of A */

the usage does not change:

import x.y.z.A

val a = A()

but the resolution is clearer with the updated factories.

updated classes:
AIAgent, AIAgentService, ToolRegistry, RollbackToolRegistry, AIAgentPlannerStrategy.

BREAKING:
The unintended usage will break, e.g. these would compile previously, but will not compile now

A.Companion.invoke()
A.invoke()
A.Companion()
etc.

now only A(...) will be allowed.

Copy link
Copy Markdown
Contributor

@devcrocod devcrocod left a comment

Choose a reason for hiding this comment

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

Good PR 👍
left a few comments

* @return An instance of an AI agent configured with the specified parameters and capable of executing its logic.
*/
@OptIn(ExperimentalUuidApi::class)
public inline operator fun <reified Input, reified Output> invoke(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Did you intentionally remove these operators without deprecating them?

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.

There is only a minor break in API, related to unintended uses of explicit invoke or Companion, so I decided not to keep deprecations here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure I fully understand about minor break
invoke operator is imported, so removing it would introduce source incompatibility for all users

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.

I did not think about this, I'll keep them as deprecated then

*
* @param init A lambda that configures the registry by adding tools
*/
public constructor(init: ToolRegistryBuilder.() -> Unit) : this(ToolRegistryBuilder().apply(init).build().tools)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

some specific logic in build?
I think you can take tools without calling build?

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.

Actually, builder.tools is private and not defined in the commonMain, so let's keep the build() here, as it was here before the refactoring

* @return A [GraphAIAgentService] instance configured with the provided parameters.
*/
@OptIn(InternalAgentsApi::class)
public inline fun <reified Input, reified Output> AIAgentService(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How would this look from Java?
Maybe it would be worth adding @JvmName

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.

These factories were not intended for use from java anyway (they were not marked @JvmStatic). Also, they are very inconvenient in java. So I think we should keep it this way and only expose AIAgent.builder for java

@antoniibelyshev antoniibelyshev force-pushed the belyshev/replace-invokes-with-factory-methods branch 3 times, most recently from 8518538 to 978414b Compare May 4, 2026 09:20
@antoniibelyshev antoniibelyshev force-pushed the belyshev/replace-invokes-with-factory-methods branch from 3ec6f9d to ee86b69 Compare May 5, 2026 10:57
@antoniibelyshev antoniibelyshev force-pushed the belyshev/replace-invokes-with-factory-methods branch 2 times, most recently from 1520297 to d17e83d Compare May 5, 2026 11:30
@antoniibelyshev antoniibelyshev force-pushed the belyshev/replace-invokes-with-factory-methods branch from d17e83d to f313079 Compare May 5, 2026 11:53
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.

2 participants