Repository navigation
[SSH] Pass Codex context via developer_instructions #7197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,8 +7,11 @@ import ( | |
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
|
|
||
| "github.com/BurntSushi/toml" | ||
| "github.com/databricks/cli/libs/atomicfile" | ||
| "github.com/databricks/cli/libs/env" | ||
| "github.com/databricks/cli/libs/shellquote" | ||
|
|
@@ -24,21 +27,48 @@ const ( | |
|
|
||
| // WorkspaceHomeEnv passes the user's workspace home to the shim for the agent context. | ||
| WorkspaceHomeEnv = "DATABRICKS_WORKSPACE_HOME" | ||
|
|
||
| // ContextFile holds the Databricks session context, under RootDir. | ||
| ContextFile = "agent-system-context.md" | ||
| ) | ||
|
|
||
| type AgentSpec struct { | ||
| Name string | ||
| TelemetryName protos.SshAgentShimAgent | ||
| // ContextFlag passes the context file via this CLI flag (Claude's --append-system-prompt-file). | ||
| ContextFlag string | ||
| // ContextHomeFile writes the context to this $HOME instructions file (codex's AGENTS.md). | ||
| ContextHomeFile string | ||
| // ContextArg puts the system context where the agent reads it, returning the | ||
| // argv to pass to the agent binary. | ||
| ContextArg func(home, systemContext string) ([]string, error) | ||
| } | ||
|
|
||
| // Currently limited to the agents whose Unity Gateway CLI command supports --workspace | ||
| var SupportedAgents = []AgentSpec{ | ||
| {Name: "claude", TelemetryName: protos.SshAgentShimAgentClaudeCode, ContextFlag: "--append-system-prompt-file"}, | ||
| {Name: "codex", TelemetryName: protos.SshAgentShimAgentCodex, ContextHomeFile: ".codex/AGENTS.md"}, | ||
| {Name: "claude", TelemetryName: protos.SshAgentShimAgentClaudeCode, ContextArg: claudeContextArg}, | ||
| {Name: "codex", TelemetryName: protos.SshAgentShimAgentCodex, ContextArg: codexContextArg}, | ||
| } | ||
|
|
||
| func claudeContextArg(home, systemContext string) ([]string, error) { | ||
| // Keep the scratch context file under the shim's own directory so it never | ||
| // clobbers an unrelated file the user happens to have in their home. | ||
| dir := filepath.Join(home, RootDir) | ||
| if err := os.MkdirAll(dir, 0o755); err != nil { | ||
| return nil, fmt.Errorf("failed to create %s: %w", dir, err) | ||
| } | ||
| f := filepath.Join(dir, ContextFile) | ||
| if err := os.WriteFile(f, []byte(systemContext), 0o644); err != nil { | ||
| return nil, fmt.Errorf("failed to write agent context file: %w", err) | ||
| } | ||
| return []string{"--append-system-prompt-file", f}, nil | ||
| } | ||
|
|
||
| func codexContextArg(home, systemContext string) ([]string, error) { | ||
| // The override value is parsed as TOML, so encode the multi-line context as | ||
| // a TOML string rather than relying on codex's raw-string fallback. | ||
| // https://github.com/openai/codex/blob/rust-v0.145.0/codex-rs/utils/cli/src/config_override.rs | ||
| kv, err := toml.Marshal(map[string]string{"developer_instructions": systemContext}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to encode agent context: %w", err) | ||
| } | ||
| return []string{"-c", strings.TrimSpace(string(kv))}, nil | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocking: this silently drops the user's own The old Repro with a real codex (0.164.0), using the exact arg this function produces ( D=$(mktemp -d); W=$(mktemp -d)
printf 'developer_instructions = "USER-OWN-INSTRUCTIONS"\n' > $D/config.toml
cd $W && git init -q
CODEX_HOME=$D codex debug prompt-input | grep -c USER-OWN-INSTRUCTIONS # 1
CODEX_HOME=$D codex -c "$(cat arg)" debug prompt-input | grep -c USER-OWN-INSTRUCTIONS # 0The second run shows only the Databricks context. Could we combine this with the user's existing value, or use a mechanism that adds rather than replaces, and bring back a test that the user's own instructions survive?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anton-107 This was intentional (for now at least) since I don't want to reimplement Codex's config resolution in order to read the existing value (if it exists). I thought this was a reasonable trade off since these are agents running in a managed setting ( If this ends up being an issue in practice we can always add the config resolution to merge our instructions with the user's
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair, I'm withdrawing "blocking". Merging would mean reimplementing Codex's layered config resolution, and |
||
| } | ||
|
|
||
| func AgentByName(name string) (AgentSpec, bool) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[blocking]ug codex -- -c developer_instructions=... <args>always givesugtwo or more passthrough args. At the pinnedugCommit,_smart_routing_launch_shapeinsrc/ucode/cli.pytreats a Codex launch as interactive only when it has no args or one explicit prompt. So_disable_smart_routing_for_subcommandturns off smart routing for every Codex session that starts through the shim, also for workspaces that turned it on. Thetool_args[:1] == ["update"]checks insrc/ucode/agents/codex.pyalso no longer matchcodex update. Agree with the Unity Gateway team on a supported way to add developer instructions, or makeugskip leading-coverrides when it picks the launch shape. Then add a Codex case toTestPrepareAgentLaunch.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is a bad heuristic. There are plenty of flags a normal user would pass to an interactive session, and with this they are opted out of smart routing.
Will fix 👍