I want an agent to run in a loop where the loop co...
# koog-agentic-framework
c
I want an agent to run in a loop where the loop control lies outside of the agent's execution graph (e.g.
while (true) { agent.step() }
). I want the chat history to persist between steps (windowing or self-redacting is fine). What's the best way to do this? For context, I want the agent to be more autonomous and run continuously, using tools to wait for periods of inactivity
s
Hi @caelum19. Could you please clarify what is the
step()
in your example? Koog agents does not have an ability to execute a particular step. You can run the whole agent strategy. Depending on the strategy, you can persist the context between runs or not. If you need to repeat some step until it mean some conditions, you can take a look on
subgraphWithRetry
that will run as part of the agent itself.
c
ok so you're saying it makes sense to make a strategy that persists messages somewhere? Btw was there something like this in the past that was removed? I think it's going to be a very desired pattern from people who came from python frameworks like CAMEL
(for reference
<https://docs.camel-ai.org/reference/camel.agents.chat_agent#step>
)
a
I'm unclear what you mean by "loop control lies outside of the agent's execution graph", but if you just want to persist messages/logs elsewhere perhaps you can use Koog's Tracing feature? Regarding that linked GitHub file, could Koog's Prompt be used instead, which already contains the full list of messages for a Session ?
While not exactly like CAMEL’s
step()
execution, there’s a PR in the works for a non-graph Koog strategy API that makes it easier to write agents imperatively for simpler cases that don’t need full graph strategies. Example from the PR:
Copy code
val agent = AIAgent(
        executor = executor,
        llmModel = OpenAIModels.Chat.GPT4o,
        strategy = simpleStrategy("calculator") { input ->
            val responses = requestLLMMultiple(input)

            while (responses.containsToolCalls()) {
                val tools = extractToolCalls(responses)

                if (latestTokenUsage(tools) > 100500) {
                    compressHistory()
                }

                val results = executeMultipleTools(tools)
                sendMultipleToolResults(results)

            }

            responses.single().asAssistantMessage().content
        },
        systemPrompt = "You are a calculator.",
        toolRegistry = toolRegistry
    )
c
oh that looks exactly like what I'm looking for! Tracing looks like how I could have otherwise done it if I could figure out how to get the recorded messages passed into future graph executions nicely
a
I think the addition in that PR will be great for conceptualizing simpler agents before translating their logic into more flexible graph-based strategies as requirements grow
c
Yeah me too. Tangentially related but I have some feelings about the way that most node delegates are
AIAgentNodeDelegate<String, String>
right now, though I probably just don't get this graph paradigm enough and I should let them be until I understand better. If anyone is free to do some pair programming on that PR where I can ask many questions then I'd love to 🙂
a
<String, String>
is just the node input/output types used in the examples/tests (representing text prompt -> text LLM output), but the input/outputs in Koog's API are generic and can be anything (e.g.
<UserQueryDataClass, SearchResultsDataClass>
) in real use cases