Hi! Ever wanted to debug running agents? Need som...
# koog-agentic-framework
v
Hi! Ever wanted to debug running agents? Need some graph visualisation or real-time tracing right in your IDE? Our colleagues from JetBrains created an AI Debugger plugin for IntelliJ that now also comes with Koog support (Koog 0.5.2+)
Disclamer: it’s in alpha version so some bugs and instabilities are possible, but please feel free to try it and let us know your thoughts
https://plugins.jetbrains.com/plugin/26921-ai-agents-debugger
kodee walking backward 3
kodee greetings 5
kodee happy 5
K 8
r
👋 This is really really cool! I do run into an issue though. I have a local script that runs an agent in my console and it's "mimicing" the A2A workflow. When the plugin is installed and I do a second pass on my agent, I get this error:
Copy code
2025-11-20 20:54:18.245Z ERROR ai.koog.agents.core.feature.remote.server.FeatureMessageRemoteServer:193 - Feature Message Remote Server. Starting server on port 56503 job was cancelled. Root exception: java.net.BindException: Address already in use
kotlinx.coroutines.JobCancellationException: LazyStandaloneCoroutine is cancelling
Caused by: java.net.BindException: Address already in use
	at java.base/sun.nio.ch.Net.bind0(Native Method) ~[?:?]
	at java.base/sun.nio.ch.Net.bind(Net.java:555) ~[?:?]
	at java.base/sun.nio.ch.ServerSocketChannelImpl.netBind(ServerSocketChannelImpl.java:337) ~[?:?]
	at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:294) ~[?:?]
	at io.ktor.network.sockets.ConnectUtilsJvmKt.tcpBind(ConnectUtilsJvm.kt:35) ~[ktor-network-jvm-3.3.0.jar:3.3.0]
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:58) ~[ktor-network-jvm-3.3.0.jar:3.3.0]
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:38) ~[ktor-network-jvm-3.3.0.jar:3.3.0]
	at io.ktor.server.cio.backend.HttpServerKt$httpServer$acceptJob$1.invokeSuspend(HttpServer.kt:46) ~[ktor-server-cio-jvm-3.2.2.jar:3.2.2]
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) [kotlin-stdlib-2.2.10.jar:2.2.10-release-430]
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100) [kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124) ~[kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89) ~[kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586) [kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820) [kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717) [kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704) [kotlinx-coroutines-core-jvm-1.10.2.jar:?]
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException
Here's my "script" that I use to test it out. I might be doing something wrong, so any help would be appreciated.
Copy code
fun main(args: Array<String>): Unit =
    runBlocking {
        val agent = IQGenericAgent(...)

        val contextId = UUID.randomUUID().toString()
        val taskStorage = InMemoryTaskStorage()
        val messageStorage = InMemoryMessageStorage()
        var taskId: String? = null

        var input: String? = "Initial question for the agent"

        while (true) {
            print("\nQuestion: ")
            val userInput = input?.let {
                print(it)
                println()
                it
            } ?: readlnOrNull() ?: break

            input = null

            val context = requestContext(
                userInput,
                user,
                contextId,
                taskId = taskId,
                taskStorage = taskStorage,
                messageStorage = messageStorage
            )
            val sessionEventProcessor = SessionEventProcessor(
		        contextId = contextId,
		        taskId = taskId,
		        taskStorage = taskStorage
		    )
            val session = LazySession(
                coroutineScope = CoroutineScope(SupervisorJob()),
                eventProcessor = sessionEventProcessor,
            ) {
                agent.execute(context, sessionEventProcessor)
            }

            launch {
                session.events
                    .collect { event ->
                        when (event) {
                            is TaskArtifactUpdateEvent -> {
                                print(event.artifact.parts.text)
                            }
                            is TaskStatusUpdateEvent -> {
                                println()
                                println("===")
                                println(event.status.state.name)
                                if (event.status.state.terminal) {
                                    taskId = null
                                }
                                event.status.message?.let {
                                    println(it.text)
                                }
                                event.metadata?.let {
                                    println(Json.encodeToString(it))
                                }
                                println()
                                println("===")
                                println()
                            }
                            is Task -> {
                                println()
                                println("===")
                                if (event.status.state == TaskState.Submitted) {
                                    taskId = event.id
                                }
                                println(event.status.state.name)
                                event.status.message?.let {
                                    println(it.text)
                                }
                                event.metadata?.let {
                                    println(Json.encodeToString(it))
                                }
                                println()
                                println("===")
                                println()
                            }
                            is Message -> {
                                println()
                                println("===")
                                println(event.parts.text)
                                event.metadata?.let {
                                    println(Json.encodeToString(it))
                                }
                                println()
                                println("===")
                                println()
                            }
                        }
                    }
            }
            session.agentJob.await()
        }
    }
Adding
agent.close()
did it for me
v
@Sergei Dubov is it a known issue?
r
Actually, running my tests in IntelliJ also have the same error (if I don't call
close()
) If I run them on my terminal, they pass
m
I’m actually facing a similar issue. I’m running agents as tools and even tho I close them after every use I keep getting the error:
Copy code
Exception in thread "DefaultDispatcher-worker-4" java.net.BindException: Address already in use
	at java.base/sun.nio.ch.Net.bind0(Native Method)
	at java.base/sun.nio.ch.Net.bind(Net.java:565)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.netBind(ServerSocketChannelImpl.java:344)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:301)
	at io.ktor.network.sockets.ConnectUtilsJvmKt.tcpBind(ConnectUtilsJvm.kt:35)
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:58)
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:38)
	at io.ktor.server.cio.backend.HttpServerKt$httpServer$acceptJob$1.invokeSuspend(HttpServer.kt:46)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
2025-11-21 18:55:04.240 [DefaultDispatcher-worker-2] ERROR a.k.a.c.f.r.s.FeatureMessageRemoteServer - Feature Message Remote Server. Starting server on port 64700 job was cancelled. Root exception: java.net.BindException: Address already in use
kotlinx.coroutines.JobCancellationException: LazyStandaloneCoroutine is cancelling
Caused by: java.net.BindException: Address already in use
	at java.base/sun.nio.ch.Net.bind0(Native Method)
	at java.base/sun.nio.ch.Net.bind(Net.java:565)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.netBind(ServerSocketChannelImpl.java:344)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:301)
	at io.ktor.network.sockets.ConnectUtilsJvmKt.tcpBind(ConnectUtilsJvm.kt:35)
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:58)
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:38)
	at io.ktor.server.cio.backend.HttpServerKt$httpServer$acceptJob$1.invokeSuspend(HttpServer.kt:46)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
Caused by: java.net.BindException: Address already in use

	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [LazyStandaloneCoroutine{Cancelling}@1f0d27c7, <http://Dispatchers.IO]|Dispatchers.IO]>
java.net.BindException: Address already in use
	at java.base/sun.nio.ch.Net.bind0(Native Method)
	at java.base/sun.nio.ch.Net.bind(Net.java:565)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.netBind(ServerSocketChannelImpl.java:344)
	at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:301)
	at io.ktor.network.sockets.ConnectUtilsJvmKt.tcpBind(ConnectUtilsJvm.kt:35)
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:58)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: null
	at io.ktor.network.sockets.TcpSocketBuilder.bind(TcpSocketBuilder.kt:38)
❌ Error in AI summarization: Address already in use
	at io.ktor.server.cio.backend.HttpServerKt$httpServer$acceptJob$1.invokeSuspend(HttpServer.kt:46)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [LazyStandaloneCoroutine{Cancelled}@1f0d27c7, <http://Dispatchers.IO]|Dispatchers.IO]>
s
@Ruben Cagnie, Thank you for reporting this. Here, agent is a closable instance. To make sure your agent is correctly finalized, it is safe to use:
Copy code
AIAgent(...).use { agent -> 
  agent.run(...)
}
Within the plugin, we set the debugger feature that is not finalized automatically. We might implement the logic that will finalize it independently from an agent in that case. I will take a look on that case.
🙏🏻 1
j
I'm running a Koog agent from within IntelliJ (2025.2.5 Ultimate Edition).....the AI Agents Debugger window pops up when I run the agent but this is all that's shown. I'm using Koog 0.5.3
s
Hi @John O'Reilly. Could you please send IDEA logs to check if you have any errors in the log? You can collect them from:
Help | Collect Logs and Diagnostic Data
. Please feel free to create a ticket if you like in the KG project here.
j
I'll submit ticket shortly.....in meantime fwiw I do see following in idea logs
Copy code
2025-11-26 10:21:55,225 [  60133]   INFO - #o.j.a.k.s.KoogDebuggerTransport$Companion - Koog client transport (url: <http://127.0.0.1:54843>): Successfully connected to Koog debugger after 8 attempts
2025-11-26 10:21:55,226 [  60134]   INFO - #o.j.a.k.s.KoogDebuggerTransport$Companion - Koog client transport (url: <http://127.0.0.1:54843>): Start health check job
2025-11-26 10:21:55,336 [  60244] SEVERE - #c.i.o.a.i.CoroutineExceptionHandlerImpl - Unhandled exception in [Kernel@hddpoj5nstf2d3sth6pj, Rete(abortOnError=false, commands=capacity=2147483647,data=[onReceive], reteState=kotlinx.coroutines.flow.StateFlowImpl@167fdd33, dbSource=ReteDbSource(reteState=kotlinx.coroutines.flow.StateFlowImpl@167fdd33)), DbSourceContextElement(kernel Kernel@hddpoj5nstf2d3sth6pj), ComponentManager(ProjectImpl@92496407), com.intellij.codeWithMe.ClientIdContextElementPrecursor@4c2a8549, CoroutineName(KoogSession), Dispatchers.Default]
java.lang.IllegalStateException: Unable to get current node name info
	at org.jetbrains.aidebugger.koog.session.KoogTraceEventsRepository.dispatchEvent(KoogTraceEventsRepository.kt:224)
	at org.jetbrains.aidebugger.koog.session.KoogTraceEventsRepository.access$dispatchEvent(KoogTraceEventsRepository.kt:26)
	at org.jetbrains.aidebugger.koog.session.KoogTraceEventsRepository$startEventsProcessing$collectEventsJob$1$1.emit(KoogTraceEventsRepository.kt:79)
	at org.jetbrains.aidebugger.koog.session.KoogTraceEventsRepository$startEventsProcessing$collectEventsJob$1$1.emit(KoogTraceEventsRepository.kt:77)
m
In my case the issue closing the agents does not seem to work. I’m creating Agents as tools so supporting multi-agent runs, not sure if that make any more sense on the issue
j
@Sergei Dubov let me know if you need any more info. I've also included link for branch where I'm seeing this in the issue.
ah, it's working if I don't provide
strategy
param for
AIAgent
Screenshot 2025-11-27 at 17.02.50.png
m
@John O'Reilly but you need strategies if you use structured outputs right? there is still a blocker I guess :(
j
yeah, I need to provide strategy so still a blocker for using this plugin
m
more feedback, trying to run a planner agent with the plugin make things fail, follwoing claudes types there is some feedback on why thius might be failing:
Copy code
Root cause: Koog 0.6.1's Debugger.installCommon() contains an unsafe cast eventContext.strategy as AIAgentGraphStrategy that runs for ALL
  pipeline types — including AIAgentFunctionalPipeline used by PlannerAIAgent. When the Debugger is auto-installed via KOOG_FEATURES env var or
  koog.features JVM option, it crashes because AIAgentPlannerStrategy does NOT extend AIAgentGraphStrategy.
v
Cc @Sergei Dubov