feat(harness): Initial Claude Code Support - #2602
Conversation
There was a problem hiding this comment.
Note to reviewer: #2595 removed some functionality that the UI needs
There was a problem hiding this comment.
Thanks! I added a bug issue here: #2613 that this PR should close.
Claude picked up that "FeedbackService" and "MemoryService" are not registered here - but they also don't seem to be used anywhere at the moment.
There was a problem hiding this comment.
FeedbackService isn't used anywhere I think, but MemoryService is required by ADK to enable memory, I'll add it in a follow up
e59e0a4 to
312dfe6
Compare
| - [x] Durable Claude session resume between turns | ||
| - [x] Claude Code built-in tools | ||
| - [x] Shared local subagents | ||
| - [x] Standalone skills and plugin-provided skills |
There was a problem hiding this comment.
Note to reviewer: This short list summarizes what has been done and what will come next for Claude harness.
Plugin provided skills are not entirely working due to #2604
Codex review[P1] Terminate the entire Claude process group — When a turn is canceled or parsing/event delivery fails while Claude has spawned a built-in tool process, signaling and killing only |
There was a problem hiding this comment.
Does this need to be nested inside of go/harness/claude/cmd/kagent-claude/main.go
Since it's the only main.go can't it just be go/harness/claude/cmd/main.go
There was a problem hiding this comment.
This is mainly for the binary to keep the kagent-claude name instead of a generic cmd, I think it matches the Kagent CLI in go/core/cli/cmd/kagent
There was a problem hiding this comment.
You can always name the binary with -o
There was a problem hiding this comment.
That's true I forgot, I'll move it 😓
| } | ||
| // These aliases preserve the existing ADK configuration API while sharing one | ||
| // runtime-neutral resource model with other Harness adapters. | ||
| type AgentPluginConfig = agentplugin.Resources |
There was a problem hiding this comment.
Why do we need all of these aliases, can't we just use the actual types?
There was a problem hiding this comment.
Is there a more secure/lighter weight node runtime we could use so we don't have to deal with the CVEs from node:22-trixie-slim
There was a problem hiding this comment.
We don't need a node runtime since it's now a native binary, I've switched to an alpine image
| const ( | ||
| claudeConfigDirEnv = "CLAUDE_CONFIG_DIR" | ||
| disableUpdaterEnv = "DISABLE_AUTOUPDATER" | ||
| googleCredsEnv = "GOOGLE_APPLICATION_CREDENTIALS" |
There was a problem hiding this comment.
The Vertex AI credentials are loaded into a /tmp file instead of the ADC default path since home directory /data is durable and snapshotted and this avoids the credentials from being persisted
|
|
||
| const ( | ||
| claudeConfigDirEnv = "CLAUDE_CONFIG_DIR" | ||
| disableUpdaterEnv = "DISABLE_AUTOUPDATER" |
There was a problem hiding this comment.
This keeps the runtime on the pinned Claude version by the image; I've changed I to DISABLE_UPDATES so both auto and manual updates are disabled. This also ensures that harness-provided env var cannot override this to re-enable update
| // Input contains compiler output and Actor-owned locations used to construct | ||
| // the Claude driver. | ||
| type Input struct { | ||
| Context context.Context |
There was a problem hiding this comment.
context shouldn't be in a struct generally, is this necessary, can we just pass it as an arg?
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
47759d9 to
1a6da57
Compare
| // Work around upstream ADK's artifact-only event conversion: its callbacks can | ||
| // mutate an artifact but cannot replace it with another A2A event. Do this before | ||
| // a2a-go persists the update; remove when ADK exposes a general event converter. | ||
| if update, ok := event.(*a2atype.TaskArtifactUpdateEvent); ok && artifactContainsToolEvent(update.Artifact) { |
| @@ -0,0 +1,18 @@ | |||
| //go:build !unix | |||
There was a problem hiding this comment.
I've renamed this to use _windows.go suffix instead, since Claude Code can only run on either unix or windows
| if durableDir == "" { | ||
| return nil, fmt.Errorf("durable directory is required") | ||
| } |
There was a problem hiding this comment.
This is a claudism, it always checks args that it doesn't need to
There was a problem hiding this comment.
Have it run through all instances like this
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Basic support for running Claude Code on Substrate and add extensible interfaces for future harness like Codex.