Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions registry/coder-labs/modules/codex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Run Codex CLI in your workspace to access OpenAI's models through the Codex inte
```tf
module "codex" {
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.2.0"
version = "4.3.0"
agent_id = coder_agent.example.id
openai_api_key = var.openai_api_key
workdir = "/home/coder/project"
Expand All @@ -32,7 +32,7 @@ module "codex" {
module "codex" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.2.0"
version = "4.3.0"
agent_id = coder_agent.example.id
openai_api_key = "..."
workdir = "/home/coder/project"
Expand All @@ -51,7 +51,7 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage
```tf
module "codex" {
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.2.0"
version = "4.3.0"
agent_id = coder_agent.example.id
workdir = "/home/coder/project"
enable_aibridge = true
Expand Down Expand Up @@ -94,7 +94,7 @@ data "coder_task" "me" {}

module "codex" {
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.2.0"
version = "4.3.0"
agent_id = coder_agent.example.id
openai_api_key = "..."
ai_prompt = data.coder_task.me.prompt
Expand All @@ -105,14 +105,34 @@ module "codex" {
}
```

### Usage with Agent Boundaries

This example shows how to configure the Codex module to run the agent behind a process-level boundary that restricts its network access.

By default, when `enable_boundary = true`, the module uses `coder boundary` subcommand (provided by Coder) without requiring any installation.

```tf
module "codex" {
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.3.0"
agent_id = coder_agent.main.id
openai_api_key = var.openai_api_key
workdir = "/home/coder/project"
enable_boundary = true
}
```

> [!NOTE]
> For developers: The module also supports installing boundary from a release version (`use_boundary_directly = true`) or compiling from source (`compile_boundary_from_source = true`). These are escape hatches for development and testing purposes.

### Advanced Configuration

This example shows additional configuration options for custom models, MCP servers, and base configuration.

```tf
module "codex" {
source = "registry.coder.com/coder-labs/codex/coder"
version = "4.2.0"
version = "4.3.0"
agent_id = coder_agent.example.id
openai_api_key = "..."
workdir = "/home/coder/project"
Expand Down
43 changes: 43 additions & 0 deletions registry/coder-labs/modules/codex/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,47 @@ describe("codex", async () => {
);
expect(configToml).toContain('profile = "aibridge"');
});

test("boundary-enabled", async () => {
const { id } = await setup({
moduleVariables: {
enable_boundary: "true",
boundary_config_path: "/tmp/test-boundary.yaml",
},
});
// Write boundary config
await execContainer(id, [
"bash",
"-c",
`cat > /tmp/test-boundary.yaml <<'EOF'
jail_type: landjail
proxy_port: 8087
log_level: warn
allowlist:
- "domain=api.openai.com"
EOF`,
]);
// Add mock coder binary for boundary setup
await writeExecutable({
containerId: id,
filePath: "/usr/bin/coder",
content: `#!/bin/bash
if [ "$1" = "boundary" ]; then
if [ "$2" = "--help" ]; then
echo "boundary help"
exit 0
fi
shift; shift; exec "$@"
fi
echo "mock coder"`,
});
await execModuleScript(id);
await expectAgentAPIStarted(id);
// Verify boundary wrapper was used in start script
const startLog = await readFileContainer(
id,
"/home/coder/.codex-module/agentapi-start.log",
);
expect(startLog).toContain("boundary");
});
});
75 changes: 55 additions & 20 deletions registry/coder-labs/modules/codex/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,36 @@ variable "codex_system_prompt" {
default = "You are a helpful coding assistant. Start every response with `Codex says:`"
}

variable "enable_boundary" {
type = bool
description = "Enable coder boundary for network filtering."
default = false
}

variable "boundary_config_path" {
type = string
description = "Path to boundary config.yaml inside the workspace. If provided, exposed as BOUNDARY_CONFIG env var."
default = ""
}

variable "boundary_version" {
type = string
description = "Boundary version. When use_boundary_directly is true, a release version should be provided or 'latest' for the latest release."
default = "latest"
}

variable "compile_boundary_from_source" {
type = bool
description = "Whether to compile boundary from source instead of using the official install script."
default = false
}

variable "use_boundary_directly" {
type = bool
description = "Whether to use boundary binary directly instead of coder boundary subcommand."
default = false
}

resource "coder_env" "openai_api_key" {
agent_id = var.agent_id
name = "OPENAI_API_KEY"
Expand Down Expand Up @@ -212,26 +242,31 @@ locals {

module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "2.2.0"

agent_id = var.agent_id
folder = local.workdir
web_app_slug = local.app_slug
web_app_order = var.order
web_app_group = var.group
web_app_icon = var.icon
web_app_display_name = var.web_app_display_name
cli_app = var.cli_app
cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null
cli_app_display_name = var.cli_app ? var.cli_app_display_name : null
module_dir_name = local.module_dir_name
install_agentapi = var.install_agentapi
agentapi_subdomain = var.subdomain
agentapi_version = var.agentapi_version
enable_state_persistence = var.enable_state_persistence
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
start_script = <<-EOT
version = "2.3.0"

agent_id = var.agent_id
folder = local.workdir
web_app_slug = local.app_slug
web_app_order = var.order
web_app_group = var.group
web_app_icon = var.icon
web_app_display_name = var.web_app_display_name
cli_app = var.cli_app
cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null
cli_app_display_name = var.cli_app ? var.cli_app_display_name : null
module_dir_name = local.module_dir_name
install_agentapi = var.install_agentapi
agentapi_subdomain = var.subdomain
agentapi_version = var.agentapi_version
enable_state_persistence = var.enable_state_persistence
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
enable_boundary = var.enable_boundary
boundary_config_path = var.boundary_config_path
boundary_version = var.boundary_version
compile_boundary_from_source = var.compile_boundary_from_source
use_boundary_directly = var.use_boundary_directly
start_script = <<-EOT
#!/bin/bash
set -o errexit
set -o pipefail
Expand Down
11 changes: 10 additions & 1 deletion registry/coder-labs/modules/codex/scripts/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,16 @@ capture_session_id() {

start_codex() {
printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}"
agentapi server --type codex --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" &
# AGENTAPI_BOUNDARY_PREFIX is set by the agentapi module's main.sh when
# enable_boundary=true. It points to a wrapper script that runs the command
# through coder boundary, sandboxing only the agent process.
if [ -n "${AGENTAPI_BOUNDARY_PREFIX:-}" ]; then
printf "Starting with coder boundary enabled\n"
agentapi server --type codex --term-width 67 --term-height 1190 -- \
"${AGENTAPI_BOUNDARY_PREFIX}" codex "${CODEX_ARGS[@]}" &
else
agentapi server --type codex --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" &
fi
capture_session_id
}

Expand Down
Loading