Skip to content

feat(go-adk): add compaction support to Go ADK runtime - #1971

Closed
yashrajshuklaaa wants to merge 3 commits into
kagent-dev:mainfrom
yashrajshuklaaa:feat/go-adk-compaction
Closed

yashrajshuklaaa wants to merge 3 commits into
kagent-dev:mainfrom
yashrajshuklaaa:feat/go-adk-compaction

Conversation

@yashrajshuklaaa

Copy link
Copy Markdown
Contributor

Implements post-invocation event history compaction for the Go ADK runtime
The upstream Go ADK v1.1.0 does not ship this so it is implemented within kagent via a new compaction package
Closes #1783

Copilot AI review requested due to automatic review settings June 6, 2026 13:07
@github-actions github-actions Bot added the enhancement New feature or request label Jun 6, 2026

Copilot AI left a comment

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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds post-invocation “context compaction” support to the Go runtime by introducing a compaction package, wiring it into the A2A executor, and enabling in-memory session event replacement.

Changes:

  • Added go/adk/pkg/compaction with configuration parsing and compaction/summarization logic.
  • Extended runner creation to return a compaction config and wired compaction into KAgentExecutor.Execute.
  • Added ReplaceEvents to local sessions to allow atomic in-memory event history rewrites after persisting a summary.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
go/core/internal/controller/reconciler/reconciler.go Updates runtime feature notes to reflect compaction support.
go/adk/pkg/session/local_session.go Adds an atomic ReplaceEvents method used by compaction.
go/adk/pkg/runner/adapter.go Returns compaction config from CreateRunnerConfig via compaction.FromAgentConfig.
go/adk/pkg/compaction/compaction.go Introduces compaction implementation and AgentConfig-to-Config translation.
go/adk/pkg/compaction/compaction_test.go Adds initial unit tests for compaction helpers and nil-compactor behavior.
go/adk/pkg/a2a/executor.go Instantiates a compactor and runs post-invocation compaction.
go/adk/cmd/main.go Plumbs compaction config into executor and logs when enabled.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/adk/pkg/session/local_session.go Resolved
Comment thread go/adk/pkg/compaction/compaction.go Resolved
Comment thread go/adk/pkg/compaction/compaction.go Resolved
Comment thread go/adk/pkg/compaction/compaction.go Resolved
Comment thread go/adk/pkg/a2a/executor.go Resolved
Implements post-invocation event history compaction for the Go ADK
runtime. The upstream Go ADK v1.1.0 does not ship this so it is
implemented within kagent via a new compaction package
Closes kagent-dev#1783

Signed-off-by: Yashraj Shukla <[email protected]>
@yashrajshuklaaa
yashrajshuklaaa force-pushed the feat/go-adk-compaction branch from ff168bb to 0b561b3 Compare June 6, 2026 13:34
@yashrajshuklaaa

Copy link
Copy Markdown
Contributor Author

@iplay88keys @jmhbh @supreme-gg-gg PTAL
addressed the comments of copilot cuz they are genuine
if u need any changes pls let me know

@yashrajshuklaaa
yashrajshuklaaa requested a review from Copilot June 8, 2026 11:26

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

go/adk/pkg/runner/adapter.go:1

  • CreateRunnerConfig now has a breaking signature change by adding *compaction.Config as a new return value. If this function is used outside this package (it’s exported), this will force cascading changes for all callers. Consider a non-breaking approach such as (a) introducing a new function (e.g., CreateRunnerConfigWithCompaction) or (b) embedding compaction config into runner.Config/an options struct to avoid widening the return tuple.
package runner

Comment on lines +251 to +265
func buildSummaryEvent(summaryText string) *adksession.Event {
e := &adksession.Event{
ID: uuid.NewString(),
InvocationID: "compaction_" + uuid.NewString(),
Timestamp: time.Now(),
Author: summaryEventAuthor,
}
e.LLMResponse = model.LLMResponse{
Content: &genai.Content{
Role: "model",
Parts: []*genai.Part{{Text: summaryText}},
},
}
return e
}
Comment on lines +224 to +249
func serializeEvents(events []*adksession.Event) string {
var sb strings.Builder
for _, e := range events {
if e.Content == nil {
continue
}
role := e.Author
if role == "" {
role = e.Content.Role
}
for _, p := range e.Content.Parts {
if p == nil {
continue
}
switch {
case p.Text != "":
fmt.Fprintf(&sb, "[%s]: %s\n", role, p.Text)
case p.FunctionCall != nil:
fmt.Fprintf(&sb, "[%s] called tool %q\n", role, p.FunctionCall.Name)
case p.FunctionResponse != nil:
fmt.Fprintf(&sb, "[tool %s response]\n", p.FunctionResponse.Name)
}
}
}
return sb.String()
}
Comment on lines +72 to +90
if len(invocations) >= c.cfg.CompactionInterval {
trigger = true
log.V(1).Info("Compaction triggered by interval",
"invocations", len(invocations),
"threshold", c.cfg.CompactionInterval)
}

if !trigger && c.cfg.TokenThreshold > 0 {
tokens := lastTokens
if tokens == 0 {
tokens = estimateTokens(allEvents)
}
if tokens >= c.cfg.TokenThreshold {
trigger = true
log.V(1).Info("Compaction triggered by token threshold",
"tokens", tokens,
"threshold", c.cfg.TokenThreshold)
}
}
Comment on lines +106 to +111
keepCount := c.cfg.OverlapSize
if keepCount >= len(invocations) {
return nil
}

toCompact := invocations[:len(invocations)-keepCount]
Comment on lines +133 to +145
if err := sessionSvc.AppendEvent(ctx, sess, summaryEvent); err != nil {
return fmt.Errorf("compaction: failed to persist summary event: %w", err)
}

var keepEvents []*adksession.Event
for _, inv := range invocations[len(invocations)-keepCount:] {
keepEvents = append(keepEvents, inv.events...)
}
// Apply EventRetentionSize cap if configured.
if c.cfg.EventRetentionSize > 0 && len(keepEvents) > c.cfg.EventRetentionSize {
keepEvents = keepEvents[len(keepEvents)-c.cfg.EventRetentionSize:]
}
replaceSessionEvents(sess, summaryEvent, keepEvents)
Comment on lines +362 to +371
// 10b. Post-invocation compaction (no-op when not configured).
// TODO: avoid the extra GetSession call by threading the session object through Execute.
if e.compactor != nil && e.sessionService != nil {
liveSess, sessErr := e.sessionService.GetSession(ctx, e.appName, userID, sessionID)
if sessErr == nil && liveSess != nil {
if compactErr := e.compactor.MaybeCompact(ctx, liveSess, e.sessionService, 0); compactErr != nil {
e.logger.Error(compactErr, "Post-invocation compaction failed (non-fatal)")
}
}
}
Comment on lines +82 to +87
if text == "" {
t.Fatal("expected non-empty serialized text")
}
if len(text) == 0 {
t.Fatal("serialized text should not be empty")
}

@EItanya EItanya left a comment

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.

Thanks for taking this on. Adding Go-runtime compaction is a useful direction, and the current PR is a helpful starting point. I took a closer look against the Python ADK compaction path, and I think there is one important design gap to resolve before merging.

The main issue is that this does not yet match Python ADK compaction semantics. Python ADK does not durably delete compacted raw events. It appends a special compaction marker event with actions.compaction containing the compacted time range and compacted content, then prompt construction later uses that marker to replace covered raw events with the summary. In this PR, the Go runtime appends a normal model-looking summary event and trims only the in-memory local session. After a fresh GetSession, the persisted store still has the raw events plus the summary, and Go ADK has no marker-aware filtering step, so the next model request can see both raw history and the summary.

That means I would treat the durable-store Copilot concern as real, but I would not solve it by deleting old backend rows unless we intentionally want different semantics from Python. A closer match would be to persist some compaction marker/range and add a Go-side prompt-time filtering layer, or otherwise wrap/filter session events before Go ADK builds LLM contents.

A few related differences from the Python implementation also seem worth addressing:

  • compaction_interval in Python means number of new invocations since the last compaction. The current Go code checks total grouped invocations, which can repeatedly compact the same logical history after reload or behave differently depending on in-memory truncation.
  • summarizer_model appears to be parsed but not used to construct SummarizerLLM. Python builds an LlmEventSummarizer from the configured model, and otherwise initializes one from the agent model.
  • token_threshold and event_retention_size are validated as a pair in Python. The Go implementation currently accepts partial token config and applies event retention to the kept events after interval compaction too, while Python uses retention for token-threshold compaction.
  • Python takes care not to compact pending function calls or split function call/function response pairs. The Go implementation serializes calls/responses into text and can drop the structured pairing from the retained context.

The smaller Copilot comments about defensive copying, sentinels, and test cleanup are either already addressed or easy to handle. The extra GetSession call is a performance concern, but I think it is secondary to getting the compaction model aligned with Python first.

Suggested acceptance test: create enough persisted events to trigger compaction, run compaction, reload the session from the backing service, then verify that the next model request sees summary plus retained events rather than raw compacted history plus summary. That would catch the main semantic issue here.

Again, thank you for pushing this forward. I think the feature is valuable; it just needs the durable marker/filtering piece before it will behave like the existing Python ADK path.

@yashrajshuklaaa

Copy link
Copy Markdown
Contributor Author

@EItanya thanks for the detailed explanation , it really helped me understand what the correct implementation should look like
I went and read through the Python ADK source ( apps/compaction.py , flows/llm_flows/contents.py , events/event_actions.py ) to understand the marker based approach you described
that makes total sense now - the compaction event carries start_timestamp , end_timestamp and compacted_content in actions.compaction and then contents.py filters out raw events that fall within that range at prompt-build time
The raw events stay in the backing store untouched.

So i checked the Go ADK module to see if the same primitives exist there. Went through every released version from v0.1.0 all the way to v1.4.0 , searching for EventCompaction , CompactedContent , StartTimestamp and any other naming variation I could think of. Nothing. The EventActions struct in Go ADK doesn't have a Compaction field at all and contents_processor.go has no filtering step for compaction markers either

@yashrajshuklaaa

Copy link
Copy Markdown
Contributor Author

so i think the right move is to contribute to EventCompaction support upstream to google.golang.org/adk first by adding the struct to EventActions and the filtering logic in contents_processor.go to mirror what Python ADK does
once that's done coming back and implementing proper marker-based compaction in kagent would be pretty straightforward

@yashrajshuklaaa

Copy link
Copy Markdown
Contributor Author

@EItanya opened an issue at https://github.com/google/adk-go after that we can continue with this

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale because of no activity in the last 15 days. It will be closed in the next 5 days unless it is tagged "no stalebot" or other activity occurs.

@github-actions github-actions Bot added the stale This issue or PR has become stale label Jun 26, 2026
pull Bot pushed a commit to TheTechOddBug/kagent that referenced this pull request Sep 20, 2026
## Problem

Since 0.10.0 the Agent CRD defaults `spec.declarative.runtime` to `go`,
and the Go runtime never read `spec.declarative.context.compaction`. The
controller compiles the field into the agent's `config.json`
(`context_config.compaction`) and the Python runtime consumes it, but a
Go agent grew its prompt with every turn regardless of what the operator
configured; the only signal was the `UnsupportedFeatures` condition
(kagent-dev#2728). Measured on an internal installation running 0.10.1: an agent
session grew from 4k to 190k input tokens per model call over 119 calls,
and every Go agent there ran without compaction because the runtime
ignored the field.

`google.golang.org/adk/v2` v2.3.0 (2026-08-31) ships native compaction
(`session/compaction`: sliding window, tail retention, LLM summarizer)
and the `runner.Config.Compaction` hook, so the runtime can consume it
instead of carrying its own port of the algorithm, which is what kagent-dev#1971
and kagent-dev#2025 attempted before the primitives existed.

## Change

- **Dependency:** `google.golang.org/adk/v2` v2.2.0 → v2.3.0. The
OpenTelemetry exporters and contrib instrumentation move to the matching
v1.45.0 / v0.21.0 / v0.70.0 set, which the new ADK version requires for
`otel/log`. otel/log v0.21.0 hands log bodies as attribute.Value; the
telemetry test on main
follows that in the same commit. No other kagent code needed changes for
the bump.
- **Runtime:** `agent.CompactionConfig` translates
`context_config.compaction` into a `compaction.Config` and
`runner.CreateRunnerConfig` hands it to the ADK runner.
`compaction_interval` / `overlap_size` drive the sliding window,
`token_threshold` / `event_retention_size` tail retention; either
strategy is off when its settings are unset, so an agent without
`context_config` runs exactly as before.
- **Half-configured settings** are ignored with a warning rather than
rejected: `token_threshold` without `event_retention_size` (and the
reverse), `overlap_size` without an interval. That mirrors the Python
runtime, where adk-python runs tail retention only when both settings
are present. What remains is validated at startup with the runner's own
rules, so a configuration the runner would refuse (negative values, no
strategy at all) fails fast with the reason instead of on the first
turn.
- **Summarizer:** `summarizer_model` builds a `compaction.LLMSummarizer`
through the same model factory as the agent (`CreateLLM`), with the
model's generation config and a 60 s bound per call (the same bound the
runner applies to its default summarizer). A `prompt_template` gets the
tool-name instruction the Python runtime appends (kagent-dev#1907), so summaries
keep namespaced tool names; a template without a summarizer model runs
on the agent's own model. With neither, the runner summarizes with the
agent's model and ADK's default prompt, matching the Python runtime.
- **Observability:** startup logs `context compaction enabled` with the
resolved values and the summarizer model, or `context compaction not
configured`, so an operator can see from the agent log what the runtime
does with the field.
- **API:** `main` had no field for compaction in the v1alpha3 API (the
0.10 line has `spec.declarative.context`), so nothing produced
`context_config`. `spec.kagent.compaction` on the `Harness` adds it,
next to `spec.kagent.memory`: `compactionInterval` / `overlapSize` for
the sliding window, `tokenThreshold` / `eventRetentionSize` for tail
retention, and an optional `summarizer` with a `modelConfigRef` (a
`ModelConfig` in the Harness namespace) and a `promptTemplate`. It is
runtime policy rather than portable agent behaviour (specific to the ADK
runner; the Claude and Codex harnesses have nothing to apply it to),
which is why it lives on the Harness and not on the `AgentTemplate`. The
CRD rejects at admission what the runtime would refuse at startup: no
strategy, `tokenThreshold` without `eventRetentionSize` (and the
reverse), `overlapSize` without `compactionInterval`, a `promptTemplate`
without `{conversation_history}`.
- **Controller:** the kagent compiler translates the Harness's
compaction policy into `context_config` in `config.json` of every root
agent the Harness runs. A summarizer `ModelConfig` other than the
agent's own is resolved from the Harness namespace like the memory
model, so its credentials and egress join the revision and a change to
it compiles a new revision; the agent's own model stays implicit because
the runtime already summarizes with it by default.

Compaction records travel on `EventActions.Compaction`; the local
DurableDir session store persists `Actions` as a whole (ADK's
`session/database`), so a summary survives an actor restart and the same
range is not summarized again.

The 0.10 line, where the field already exists on the Agent CRD and the
reconciler flagged it as unsupported, is kagent-dev#2791.

## Testing

- `go test ./adk/pkg/agent/`: `TestCompactionStrategies` (table: each
strategy alone and combined, unset settings, the three half-configured
cases, no strategy, negative values), `TestCompactionConfig` (not
configured → nil; default summarizer; dedicated summarizer model; custom
prompt on the agent model; prompt without `{conversation_history}`
rejected; prompt without any model rejected; the `context_config` block
as the controller compiles it),
`TestCompactionSlidingWindowFiresAfterInterval` (a scripted model drives
the ADK runner: no record after turn 1, one record after turn 2 whose
content is the summarizer's reply, and turn 3's request shows the
summary and none of the compacted turns),
`TestCompactionTailRetentionFiresOverTokenThreshold`.
- `go test ./core/internal/translator/...`: `TestApplyCompaction` (not
configured → no `context_config`; all four settings and a prompt on the
agent model → mapped with no `summarizer_model`; a dedicated summarizer
`ModelConfig` → its model in `config.json`, its credential in the
environment, its host in the egress, itself in the provenance models; a
missing summarizer `ModelConfig` → error).
- `go test ./api/v1alpha3/` (envtest): the five new CEL cases reject
each half configuration with its message, and the fully configured
Harness is accepted.
- `make -C go test`: all packages pass.
- `make -C go lint`: 0 issues.

## End-to-end

`TestAgentInstanceContextCompaction` (in the `test-e2e` job) runs the
whole chain with `mockllm` as the summarizer: a clone of the suite's
`kagent` Harness with `compactionInterval: 2` and a dedicated summarizer
`ModelConfig`, admitting a plain `AgentTemplate`; both models point at
one mock LLM behind a recording proxy on the test host; a default header
on each `ModelConfig` tells the two models apart. Three turns through
the public A2A API, then the recorded requests show what the runtime
sent: the summarizer model was called exactly once, after the second
turn, with both turns in the transcript and the custom prompt; the
second turn's request still carried the first turn raw; the third turn's
request carries the summary and none of the four compacted messages. Run
before pushing against a local kind cluster with Substrate 0.0.26 and
the controller and Go ADK images built from this branch: passes in 4.9
s.

The real-model run (kind, images built from the branch, Anthropic
`claude-haiku-4-5`, a five-turn tool-using conversation: turn 5 needs
2,524 prompt tokens with compaction against 50,247 without) was done on
the 0.10 backport kagent-dev#2791. The runtime code is the same on both branches
apart from the logging package (`log/slog` here, logr on 0.10).

Refs kagent-dev#2728 (closed by kagent-dev#2791 for the 0.10 line; on `main` the field
returns with the v1alpha3 API).

---------

Signed-off-by: Timo Derstappen <[email protected]>
alexdarbyshire pushed a commit to alexdarbyshire/kagent that referenced this pull request Oct 5, 2026
## Problem

Since 0.10.0 the Agent CRD defaults `spec.declarative.runtime` to `go`,
and the Go runtime never read `spec.declarative.context.compaction`. The
controller compiles the field into the agent's `config.json`
(`context_config.compaction`) and the Python runtime consumes it, but a
Go agent grew its prompt with every turn regardless of what the operator
configured; the only signal was the `UnsupportedFeatures` condition
(kagent-dev#2728). Measured on an internal installation running 0.10.1: an agent
session grew from 4k to 190k input tokens per model call over 119 calls,
and every Go agent there ran without compaction because the runtime
ignored the field.

`google.golang.org/adk/v2` v2.3.0 (2026-08-31) ships native compaction
(`session/compaction`: sliding window, tail retention, LLM summarizer)
and the `runner.Config.Compaction` hook, so the runtime can consume it
instead of carrying its own port of the algorithm, which is what kagent-dev#1971
and kagent-dev#2025 attempted before the primitives existed.

## Change

- **Dependency:** `google.golang.org/adk/v2` v2.2.0 → v2.3.0. The
OpenTelemetry exporters and contrib instrumentation move to the matching
v1.45.0 / v0.21.0 / v0.70.0 set, which the new ADK version requires for
`otel/log`. otel/log v0.21.0 hands log bodies as attribute.Value; the
telemetry test on main
follows that in the same commit. No other kagent code needed changes for
the bump.
- **Runtime:** `agent.CompactionConfig` translates
`context_config.compaction` into a `compaction.Config` and
`runner.CreateRunnerConfig` hands it to the ADK runner.
`compaction_interval` / `overlap_size` drive the sliding window,
`token_threshold` / `event_retention_size` tail retention; either
strategy is off when its settings are unset, so an agent without
`context_config` runs exactly as before.
- **Half-configured settings** are ignored with a warning rather than
rejected: `token_threshold` without `event_retention_size` (and the
reverse), `overlap_size` without an interval. That mirrors the Python
runtime, where adk-python runs tail retention only when both settings
are present. What remains is validated at startup with the runner's own
rules, so a configuration the runner would refuse (negative values, no
strategy at all) fails fast with the reason instead of on the first
turn.
- **Summarizer:** `summarizer_model` builds a `compaction.LLMSummarizer`
through the same model factory as the agent (`CreateLLM`), with the
model's generation config and a 60 s bound per call (the same bound the
runner applies to its default summarizer). A `prompt_template` gets the
tool-name instruction the Python runtime appends (kagent-dev#1907), so summaries
keep namespaced tool names; a template without a summarizer model runs
on the agent's own model. With neither, the runner summarizes with the
agent's model and ADK's default prompt, matching the Python runtime.
- **Observability:** startup logs `context compaction enabled` with the
resolved values and the summarizer model, or `context compaction not
configured`, so an operator can see from the agent log what the runtime
does with the field.
- **API:** `main` had no field for compaction in the v1alpha3 API (the
0.10 line has `spec.declarative.context`), so nothing produced
`context_config`. `spec.kagent.compaction` on the `Harness` adds it,
next to `spec.kagent.memory`: `compactionInterval` / `overlapSize` for
the sliding window, `tokenThreshold` / `eventRetentionSize` for tail
retention, and an optional `summarizer` with a `modelConfigRef` (a
`ModelConfig` in the Harness namespace) and a `promptTemplate`. It is
runtime policy rather than portable agent behaviour (specific to the ADK
runner; the Claude and Codex harnesses have nothing to apply it to),
which is why it lives on the Harness and not on the `AgentTemplate`. The
CRD rejects at admission what the runtime would refuse at startup: no
strategy, `tokenThreshold` without `eventRetentionSize` (and the
reverse), `overlapSize` without `compactionInterval`, a `promptTemplate`
without `{conversation_history}`.
- **Controller:** the kagent compiler translates the Harness's
compaction policy into `context_config` in `config.json` of every root
agent the Harness runs. A summarizer `ModelConfig` other than the
agent's own is resolved from the Harness namespace like the memory
model, so its credentials and egress join the revision and a change to
it compiles a new revision; the agent's own model stays implicit because
the runtime already summarizes with it by default.

Compaction records travel on `EventActions.Compaction`; the local
DurableDir session store persists `Actions` as a whole (ADK's
`session/database`), so a summary survives an actor restart and the same
range is not summarized again.

The 0.10 line, where the field already exists on the Agent CRD and the
reconciler flagged it as unsupported, is kagent-dev#2791.

## Testing

- `go test ./adk/pkg/agent/`: `TestCompactionStrategies` (table: each
strategy alone and combined, unset settings, the three half-configured
cases, no strategy, negative values), `TestCompactionConfig` (not
configured → nil; default summarizer; dedicated summarizer model; custom
prompt on the agent model; prompt without `{conversation_history}`
rejected; prompt without any model rejected; the `context_config` block
as the controller compiles it),
`TestCompactionSlidingWindowFiresAfterInterval` (a scripted model drives
the ADK runner: no record after turn 1, one record after turn 2 whose
content is the summarizer's reply, and turn 3's request shows the
summary and none of the compacted turns),
`TestCompactionTailRetentionFiresOverTokenThreshold`.
- `go test ./core/internal/translator/...`: `TestApplyCompaction` (not
configured → no `context_config`; all four settings and a prompt on the
agent model → mapped with no `summarizer_model`; a dedicated summarizer
`ModelConfig` → its model in `config.json`, its credential in the
environment, its host in the egress, itself in the provenance models; a
missing summarizer `ModelConfig` → error).
- `go test ./api/v1alpha3/` (envtest): the five new CEL cases reject
each half configuration with its message, and the fully configured
Harness is accepted.
- `make -C go test`: all packages pass.
- `make -C go lint`: 0 issues.

## End-to-end

`TestAgentInstanceContextCompaction` (in the `test-e2e` job) runs the
whole chain with `mockllm` as the summarizer: a clone of the suite's
`kagent` Harness with `compactionInterval: 2` and a dedicated summarizer
`ModelConfig`, admitting a plain `AgentTemplate`; both models point at
one mock LLM behind a recording proxy on the test host; a default header
on each `ModelConfig` tells the two models apart. Three turns through
the public A2A API, then the recorded requests show what the runtime
sent: the summarizer model was called exactly once, after the second
turn, with both turns in the transcript and the custom prompt; the
second turn's request still carried the first turn raw; the third turn's
request carries the summary and none of the four compacted messages. Run
before pushing against a local kind cluster with Substrate 0.0.26 and
the controller and Go ADK images built from this branch: passes in 4.9
s.

The real-model run (kind, images built from the branch, Anthropic
`claude-haiku-4-5`, a five-turn tool-using conversation: turn 5 needs
2,524 prompt tokens with compaction against 50,247 without) was done on
the 0.10 backport kagent-dev#2791. The runtime code is the same on both branches
apart from the logging package (`log/slog` here, logr on 0.10).

Refs kagent-dev#2728 (closed by kagent-dev#2791 for the 0.10 line; on `main` the field
returns with the v1alpha3 API).

---------

Signed-off-by: Timo Derstappen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request stale This issue or PR has become stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add compaction to golang ADK

3 participants