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>
|
There is too much happening in this PR for a focused review. Please split the ToolService / RemoteMCPServer / MCPServer changes into a separate PR and keep this one scoped to the Claude harness work. Those changes have their own catalog, reconciliation, lifecycle, and UI implications and need focused review and testing on their own. |
Basic support for running Claude Code on Substrate and add extensible interfaces for future harness like Codex.