diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index df486812c..5e8ac2729 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -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" @@ -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" @@ -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 @@ -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 @@ -105,6 +105,26 @@ 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. @@ -112,7 +132,7 @@ This example shows additional configuration options for custom models, MCP serve ```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" diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index f8d9f0a59..3eff3ecad 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -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"); + }); }); diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index dd70fdc48..4d9c5ae14 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -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" @@ -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 diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index e0e7d9725..0dbf5a603 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -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 }