Skip to content

feat(agent): add full agent configuration support#115

Merged
feloy merged 3 commits intoopenkaiden:mainfrom
feloy:agent-config
Mar 26, 2026
Merged

feat(agent): add full agent configuration support#115
feloy merged 3 commits intoopenkaiden:mainfrom
feloy:agent-config

Conversation

@feloy
Copy link
Copy Markdown
Contributor

@feloy feloy commented Mar 26, 2026

Agent is now a required field when registering workspaces, specified via --agent flag or KORTEX_CLI_DEFAULT_AGENT environment variable. Agent name is displayed in workspace list and init outputs. Terminal command uses the agent's configured terminal_command from runtime config, allowing different agents to have different default terminal commands.

Podman runtime changed from hardcoded "claude" user/group to generic "agent" user/group, making the runtime more flexible for different agents.

All documentation updated to reflect agent requirements and usage.

Closes #114

Agent is now a required field when registering workspaces, specified
via --agent flag or KORTEX_CLI_DEFAULT_AGENT environment variable.
Agent name is displayed in workspace list and init outputs. Terminal
command uses the agent's configured terminal_command from runtime config,
allowing different agents to have different default terminal commands.

Podman runtime changed from hardcoded "claude" user/group to generic
"agent" user/group, making the runtime more flexible for different agents.

All documentation updated to reflect agent requirements and usage.

Closes openkaiden#114

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 82.97872% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/runtime/podman/terminal.go 55.55% 2 Missing and 2 partials ⚠️
pkg/instances/instance.go 50.00% 2 Missing ⚠️
pkg/runtime/podman/create.go 60.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Threads an explicit agent identity through CLI, instance, manager, and Podman runtime layers: --agent (or KORTEX_CLI_DEFAULT_AGENT) is required/resolved, agent is persisted on instances and surfaced in outputs, Podman artifacts replace hardcoded "claude" with a configurable container user, and runtime-driven terminal command resolution is supported when no command is provided.

Changes

Cohort / File(s) Summary
Docs & Dependency
README.md, go.mod
README examples updated to always specify --agent; added KORTEX_CLI_DEFAULT_AGENT docs and agent resolution order; bumped kortex-cli-api/cli/go dependency version.
CLI: init, list, terminal, conversion
pkg/cmd/init.go, pkg/cmd/workspace_list.go, pkg/cmd/workspace_terminal.go, pkg/cmd/conversion.go
init preRun now requires/resolves agent (flag → env → error); verbose/text/JSON outputs include agent; stopped injecting hardcoded "claude" terminal command so runtime can choose when command is empty.
CLI Tests
pkg/cmd/init_test.go, pkg/cmd/stdout_test.go, pkg/cmd/terminal_test.go, pkg/cmd/workspace_terminal_test.go, pkg/cmd/conversion_test.go
Updated tests to pass/expect --agent test-agent; added preRun resolution and precedence tests; adjusted expectations for converted workspace JSON and output strings.
Instance model & manager plumbing
pkg/instances/instance.go, pkg/instances/manager.go
Added Agent to InstanceData and Instance interface (GetAgent()); persist and propagate agent through Add/Start/Stop; Manager.Terminal now passes agent to runtime Terminal.
Instance & Manager Tests
pkg/instances/manager_test.go, pkg/instances/manager_terminal_test.go
Test doubles include Agent and GetAgent(); terminal tests assert runtime received agent parameter; Update AddOptions usage in tests.
Runtime abstraction
pkg/runtime/runtime.go
Added Agent string to exported CreateParams; changed exported Terminal interface to Terminal(ctx, instanceID, agent, command) error.
Podman runtime implementation & constants
pkg/runtime/podman/constants/constants.go, pkg/runtime/podman/create.go, pkg/runtime/podman/containerfile.go, pkg/runtime/podman/config/config.go, pkg/runtime/podman/config/defaults.go
Introduced constants package (BaseImageRegistry, ContainerUser/Group = agent); validate CreateParams.Agent; load agent config by name; replace hardcoded claude paths/user/group with constants.ContainerUser; updated error text.
Podman runtime terminal & tests
pkg/runtime/podman/terminal.go, pkg/runtime/podman/terminal_test.go, pkg/runtime/podman/create_test.go, pkg/runtime/podman/containerfile_test.go
Runtime Terminal accepts agent and derives terminal command from agent config when command is empty; tests updated for agent parameter and /home/agent/... paths; create tests adapted to new agent requirement.
Other tests & small changes
pkg/cmd/stdout_test.go, pkg/cmd/workspace_terminal_test.go, pkg/runtime/podman/containerfile_test.go
Various tests adjusted to new agent behavior and user/path constants; string assertions updated to use agent.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI User
    participant InitCmd as init Command
    participant Manager as Instance Manager
    participant Runtime as Podman Runtime
    participant AgentCfg as Agent Config

    rect rgba(100,149,237,0.5)
    CLI->>InitCmd: init --agent claude --runtime podman
    InitCmd->>InitCmd: preRun: resolve agent (flag → KORTEX_CLI_DEFAULT_AGENT → error)
    InitCmd->>Manager: Add(opts {Agent: "claude", ...})
    Manager->>Runtime: Create(ctx, params {Agent: "claude", ...})
    Runtime->>AgentCfg: LoadAgent("claude")
    AgentCfg-->>Runtime: agent configuration
    end

    rect rgba(144,238,144,0.5)
    CLI->>InitCmd: workspace terminal (no COMMAND)
    InitCmd->>Manager: Terminal(instanceID, agent, [])
    Manager->>Runtime: Terminal(ctx, instanceID, "claude", [])
    Runtime->>AgentCfg: LoadAgent("claude")
    AgentCfg-->>Runtime: TerminalCommand
    Runtime->>Runtime: exec -it <instanceID> <agentTerminalCmd>
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The PR description provides relevant details about agent requirements, display in outputs, terminal command behavior, and Podman runtime changes, all matching the changeset.
Linked Issues check ✅ Passed The PR comprehensively implements all requirements from issue #114: agent becomes required with fallback to KORTEX_CLI_DEFAULT_AGENT [#114], agent displayed in outputs [#114], manager.Terminal accepts empty command with runtime selecting based on agent config [#114], Podman user/group generalized to 'agent' [#114], CreateParams extended with Agent field [#114].
Out of Scope Changes check ✅ Passed All changes directly support the stated objectives: README documentation updates, agent requirement enforcement, instance/manager agent field additions, Podman containerfile/config refactoring, and runtime interface extensions align with issue #114 requirements.
Title check ✅ Passed The title 'feat(agent): add full agent configuration support' clearly and specifically summarizes the main change: implementing comprehensive agent configuration throughout the CLI.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
README.md (1)

175-187: ⚠️ Potential issue | 🟡 Minor

Missing agent field in JSON example.

The "Step 8: Verify removal" JSON output example is missing the "agent" field that should be present in workspace list output, unlike the other examples at lines 100-122 which correctly include it.

📝 Suggested fix
 {
   "items": [
     {
       "id": "f6e5d4c3b2a1098765432109876543210987654321098765432109876543210a",
       "name": "another-project",
+      "agent": "claude",
       "paths": {
         "source": "/absolute/path/to/another-project",
         "configuration": "/absolute/path/to/another-project/.kortex"
       }
     }
   ]
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 175 - 187, The JSON example in the "Step 8: Verify
removal" output is missing the required "agent" field; update the example object
inside the "items" array (the entry with id "f6e5d4c3b2a1...a" and name
"another-project") to include the same "agent" key/structure used by the other
workspace examples so the workspace list output matches the expected schema.
pkg/runtime/runtime.go (1)

93-96: ⚠️ Potential issue | 🟡 Minor

Documentation example shows outdated method signature.

The example code in the docstring still uses the old 3-parameter signature Terminal(ctx, instanceID string, command []string) but the interface now requires 4 parameters including agent.

📝 Suggested fix
 // Example implementation:
 //
 //	type myRuntime struct {
 //	    // ... other fields
 //	}
 //
-//	func (r *myRuntime) Terminal(ctx context.Context, instanceID string, command []string) error {
+//	func (r *myRuntime) Terminal(ctx context.Context, instanceID string, agent string, command []string) error {
 //	    // Execute command interactively (stdin/stdout/stderr connected)
 //	    return r.exec.RunInteractive(ctx, "exec", "-it", instanceID, command...)
 //	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/runtime/runtime.go` around lines 93 - 96, The docstring/example uses the
old Terminal(ctx, instanceID string, command []string) signature; update all
examples and the method implementation to the current four-parameter signature
including the agent (e.g., Terminal(ctx context.Context, agent string,
instanceID string, command []string)), and adjust any calls to
myRuntime.Terminal and other implementations to pass the agent through to the
underlying exec.RunInteractive call (or equivalent) so the example and
implementation match the interface.
🧹 Nitpick comments (1)
pkg/runtime/podman/config/defaults.go (1)

61-61: Hardcoded /home/agent path creates coupling with ContainerUser constant.

This path is hardcoded while containerfile.go defines ContainerUser = "agent" as a constant. If ContainerUser changes, this default will become inconsistent.

However, since RunCommands are serialized to JSON config files that users can customize, and the config package shouldn't depend on the podman package (to avoid circular imports), this is acceptable as-is.

Consider adding a comment noting the dependency on the container user being "agent".

📝 Suggested documentation
 	RunCommands: []string{
 		"curl -fsSL --proto-redir '-all,https' --tlsv1.3 https://claude.ai/install.sh | bash",
+		// Note: /home/agent must match ContainerUser in containerfile.go
 		"mkdir -p /home/agent/.config",
 	},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/runtime/podman/config/defaults.go` at line 61, The default RunCommands
entry contains a hardcoded "/home/agent/.config" path which couples this package
to the container user defined as ContainerUser = "agent" in containerfile.go;
add a brief comment next to the RunCommands/defaults entry explaining that the
path assumes the container user is "agent" (and that users can override the
serialized JSON if they change the user), referencing ContainerUser and the
literal "/home/agent/.config" so future readers know why the hardcode exists and
to avoid introducing a podman package import.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@pkg/runtime/runtime.go`:
- Around line 93-96: The docstring/example uses the old Terminal(ctx, instanceID
string, command []string) signature; update all examples and the method
implementation to the current four-parameter signature including the agent
(e.g., Terminal(ctx context.Context, agent string, instanceID string, command
[]string)), and adjust any calls to myRuntime.Terminal and other implementations
to pass the agent through to the underlying exec.RunInteractive call (or
equivalent) so the example and implementation match the interface.

In `@README.md`:
- Around line 175-187: The JSON example in the "Step 8: Verify removal" output
is missing the required "agent" field; update the example object inside the
"items" array (the entry with id "f6e5d4c3b2a1...a" and name "another-project")
to include the same "agent" key/structure used by the other workspace examples
so the workspace list output matches the expected schema.

---

Nitpick comments:
In `@pkg/runtime/podman/config/defaults.go`:
- Line 61: The default RunCommands entry contains a hardcoded
"/home/agent/.config" path which couples this package to the container user
defined as ContainerUser = "agent" in containerfile.go; add a brief comment next
to the RunCommands/defaults entry explaining that the path assumes the container
user is "agent" (and that users can override the serialized JSON if they change
the user), referencing ContainerUser and the literal "/home/agent/.config" so
future readers know why the hardcode exists and to avoid introducing a podman
package import.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 504fad6b-11b0-4b9f-bfff-3e366139c557

📥 Commits

Reviewing files that changed from the base of the PR and between db4919c and 278ed42.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (24)
  • README.md
  • go.mod
  • pkg/cmd/conversion.go
  • pkg/cmd/conversion_test.go
  • pkg/cmd/init.go
  • pkg/cmd/init_test.go
  • pkg/cmd/stdout_test.go
  • pkg/cmd/terminal_test.go
  • pkg/cmd/workspace_list.go
  • pkg/cmd/workspace_terminal.go
  • pkg/cmd/workspace_terminal_test.go
  • pkg/instances/instance.go
  • pkg/instances/manager.go
  • pkg/instances/manager_terminal_test.go
  • pkg/instances/manager_test.go
  • pkg/runtime/podman/config/config.go
  • pkg/runtime/podman/config/defaults.go
  • pkg/runtime/podman/containerfile.go
  • pkg/runtime/podman/containerfile_test.go
  • pkg/runtime/podman/create.go
  • pkg/runtime/podman/create_test.go
  • pkg/runtime/podman/terminal.go
  • pkg/runtime/podman/terminal_test.go
  • pkg/runtime/runtime.go

Signed-off-by: Philippe Martin <phmartin@redhat.com>

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/runtime/podman/create.go (1)

178-190: ⚠️ Potential issue | 🔴 Critical

Validate and normalize config mount paths to prevent directory traversal attacks.

Config paths from mounts.configs can escape the home directory root. While the validation in pkg/config/config.go correctly rejects absolute paths, it does not prevent traversal sequences like .., allowing entries such as ../../etc/passwd to pass validation as "relative" paths. When filepath.Join(homeDir, "../../etc/passwd") executes, it normalizes to /etc/passwd, mounting arbitrary host files. The same vulnerability exists for container-side paths via path.Join().

Validate by normalizing with filepath.Clean() and rejecting paths that resolve to ., .., absolute paths, or contain leading traversal sequences before joining.

Suggested fix
 		if params.WorkspaceConfig.Mounts.Configs != nil {
 			homeDir, err := os.UserHomeDir()
 			if err != nil {
 				return nil, fmt.Errorf("failed to get home directory: %w", err)
 			}
 			for _, conf := range *params.WorkspaceConfig.Mounts.Configs {
-				// Convert config path from forward slashes to OS-specific separators
-				confOSPath := filepath.FromSlash(conf)
-				confAbsPath := filepath.Join(homeDir, confOSPath)
+				cleanConf := filepath.Clean(filepath.FromSlash(conf))
+				if cleanConf == "." || cleanConf == ".." || filepath.IsAbs(cleanConf) ||
+					strings.HasPrefix(cleanConf, ".."+string(filepath.Separator)) {
+					return nil, fmt.Errorf("%w: config path %q must stay within the user's home directory", runtime.ErrInvalidParams, conf)
+				}
+				confAbsPath := filepath.Join(homeDir, cleanConf)
 				// HOME in container is /home/<user> for the image
 				// Use path.Join for container paths to ensure forward slashes
-				confMountPoint := path.Join(fmt.Sprintf("/home/%s", constants.ContainerUser), conf)
+				confMountPoint := path.Join("/home", constants.ContainerUser, filepath.ToSlash(cleanConf))
 				args = append(args, "-v", fmt.Sprintf("%s:%s:Z", confAbsPath, confMountPoint))
 			}
 		}

Note: The same vulnerability exists in the dependencies mounting code (lines 165–174) and requires the same fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/runtime/podman/create.go` around lines 178 - 190, The config mount
handling (params.WorkspaceConfig.Mounts.Configs) must reject paths that
normalize outside the home directory: before joining to homeDir call
filepath.Clean on conf (use confOSPath :=
filepath.Clean(filepath.FromSlash(conf))), then reject if
filepath.IsAbs(confOSPath) or confOSPath == "." or confOSPath == ".." or any
path segment equals ".." (split and check); only then compute confAbsPath :=
filepath.Join(homeDir, confOSPath). Similarly sanitize the container side mount
point using path.Clean on the container-relative path and reject container paths
that are absolute or contain ".."; apply the identical validation for the
dependencies mount loop as well so neither host nor container mount targets can
escape intended directories (refer to params.WorkspaceConfig.Mounts.Configs,
constants.ContainerUser and the dependencies mount handling).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/runtime/runtime.go`:
- Around line 62-63: Update the documentation for CreateParams.Agent to declare
it as required and non-empty (do not state "optional/can be empty"); callers and
test doubles should treat CreateParams.Agent as a mandatory field. Specifically,
change the comment on the CreateParams.Agent field to state it must be a
non-empty agent name, and ensure any tests or mocks don't rely on "" as a valid
value; this aligns with the runtime/podman create logic that rejects empty
agents (see CreateParams.Agent and the validation in
pkg/runtime/podman/create.go).

In `@README.md`:
- Around line 1261-1270: The README contains several init examples that still
call the literal command "kortex-cli init ... --runtime ..." without the
now-required agent, which will fail; update each example that shows "kortex-cli
init ... --runtime ..." (the occurrences mentioned in the review) to include an
explicit agent flag (e.g., add "--agent <agent-name>") or show how to set
KORTEX_CLI_DEFAULT_AGENT in the environment before running the command, and
ensure the examples consistently demonstrate either the CLI flag approach or the
environment-variable approach so copy-pasted commands succeed.
- Around line 554-556: Replace the sample README command "mkdir
/home/agent/.config" with the idempotent form "mkdir -p /home/agent/.config" so
it matches the generated default that uses "mkdir -p /home/<user>/.config";
update the README sample agent config so copy-pasting preserves behavior and
avoids errors when the directory already exists.

---

Outside diff comments:
In `@pkg/runtime/podman/create.go`:
- Around line 178-190: The config mount handling
(params.WorkspaceConfig.Mounts.Configs) must reject paths that normalize outside
the home directory: before joining to homeDir call filepath.Clean on conf (use
confOSPath := filepath.Clean(filepath.FromSlash(conf))), then reject if
filepath.IsAbs(confOSPath) or confOSPath == "." or confOSPath == ".." or any
path segment equals ".." (split and check); only then compute confAbsPath :=
filepath.Join(homeDir, confOSPath). Similarly sanitize the container side mount
point using path.Clean on the container-relative path and reject container paths
that are absolute or contain ".."; apply the identical validation for the
dependencies mount loop as well so neither host nor container mount targets can
escape intended directories (refer to params.WorkspaceConfig.Mounts.Configs,
constants.ContainerUser and the dependencies mount handling).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c678ea4e-48b3-4e80-b71e-1c2f7a58ca01

📥 Commits

Reviewing files that changed from the base of the PR and between 278ed42 and 95bb3e1.

📒 Files selected for processing (6)
  • README.md
  • pkg/runtime/podman/config/defaults.go
  • pkg/runtime/podman/constants/constants.go
  • pkg/runtime/podman/containerfile.go
  • pkg/runtime/podman/create.go
  • pkg/runtime/runtime.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/runtime/podman/config/defaults.go
  • pkg/runtime/podman/containerfile.go

Signed-off-by: Philippe Martin <phmartin@redhat.com>
@feloy feloy changed the title feat(agent): add full agent configuration support feat(agent): add full agent configuration support Mar 26, 2026
@feloy feloy merged commit ac72ad2 into openkaiden:main Mar 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

full support of agent configuration

3 participants