AI Catchup

Codex Hooks and Programmatic Access Tokens: Setup, Trust Model, and What Actually Runs Today

By 21 min read

Codex access tokens are ChatGPT Business and Enterprise workspace credentials for non-interactive Codex CLI runs. Create one at chatgpt.com/admin/access-tokens, then authenticate with CODEX_ACCESS_TOKEN or codex login --with-access-token. Hooks are the in-session extensibility framework: eleven lifecycle events. As of August 2026, command and mcp_tool handlers execute; at launch only command handlers did.

Two OpenAI-documented capabilities are what make Codex automatable around your own code, and they solve different halves of the problem. Hooks inject scripts at named points in the Codex agent loop -- validators, secret scanners, conversation logging, per-repo behavior. Programmatic access tokens give ChatGPT Business and Enterprise teams a workspace credential for non-interactive CI, release, and internal automation, created from the admin console with finite expirations and revocation.

For context on where Codex CLI itself surfaces hooks, our coverage of Codex CLI 0.129.0's /hooks browser is the relevant CLI-side anchor; for the headless app-server entry point most automation will pair with, see Codex CLI 0.130.0's codex remote-control.

Key Takeaways

  • Hooks are an extensibility framework, not a single feature. They inject scripts at eleven named lifecycle events, from SessionStart through Stop.
  • Enabled by default is not the same as trusted. A non-managed command hook is skipped until you review and trust it in /hooks; trust is recorded against the hook's hash, so editing a hook re-arms the review.
  • Only type: "command" handlers execute today. prompt and agent handlers are parsed but skipped. (updated August 28, 2026: command and mcp_tool handlers now execute; prompt and agent handlers are still parsed but skipped.)
  • Background hooks now work. "async": true runs a command handler while Codex continues, up to eight concurrently per session. This reverses a documented limitation this article carried until August 21, 2026.
  • Hooks are a guardrail, not an enforcement boundary. Hosted tools such as WebSearch never hit the local hook path, and the docs say so explicitly.
  • Enterprise-managed hooks are defined inline in requirements.toml, and admins can pin the hooks feature on or off there regardless of local config.
  • Access tokens authenticate non-interactive Codex CLI and app-server runs with a ChatGPT workspace identity. Business and Enterprise workspaces only, created at chatgpt.com/admin/access-tokens.
  • Use CODEX_ACCESS_TOKEN for ephemeral runs, codex login --with-access-token for a persistent local login. Copy the token at creation; you cannot view it again.
  • A personal token carries its creator's access. The workspace permission governs who may create tokens, not what a token may do.
  • Service accounts are the non-human identity. A workspace owner or admin creates a service account with its own roles, groups, and plugins, and tokens minted from its detail page represent the account rather than a person. Codex CLI 0.142.0 or later, pay-as-you-go plans only.

What Hooks Actually Do

The official Hooks docs describe an extensibility framework, not a single feature. The patterns called out:

  • Logging and analytics. Forward agent activity to internal observability systems for review, audit, or quality scoring.
  • Block pasted API keys. Pre-prompt hooks that scan input for credentials and refuse to forward them to the model.
  • Persistent memories. Hooks that read and write durable state across runs, materializing repo-specific or directory-specific behavior.
  • Validation at turn stop. Run a validator (typecheck, lint, custom rule) when the agent finishes a turn and surface failures.
  • Directory-based prompting. Customize behavior per repo or per directory so the agent treats different parts of a codebase with different policies.

Hooks are enabled by default. Codex discovers them next to active config layers, either as a hooks.json file or as inline hooks tables inside config.toml; installed plugins can bundle their own through a plugin manifest. In practice the four locations that matter are ~/.codex/hooks.json, ~/.codex/config.toml, <repo>/.codex/hooks.json, and <repo>/.codex/config.toml. Matching hooks from every source run -- a higher-precedence layer does not replace a lower one -- and multiple matching command hooks for the same event launch concurrently, so one hook cannot stop another from starting. Project-local hooks load only when the project's .codex/ layer is trusted.

To turn hooks off entirely, set hooks = false under [features] in config.toml. hooks is the canonical feature key; codex_hooks still works as a deprecated alias.

The Eleven Lifecycle Events

Earlier versions of this article described hook points loosely. The current doc names all eleven, which is what you actually configure against:

EventWhen it firesWhat it is for
SessionStartSession begins: startup, resume, clear, or compactLoad conventions or session notes as developer context
SessionEndMain thread ends (not for subagents)Save final notes, clean up. Advisory only, 1s default timeout
SubagentStartA subagent startsApply per-subagent policy by agent_type
SubagentStopA subagent finishesAsk Codex to continue the subagent with a reason
UserPromptSubmitBefore a prompt is sent to the modelScan input for credentials; inject extra context
PreToolUseBefore a tool callBlock or rewrite the call
PermissionRequestCodex is about to ask for approvalAuto-approve, deny, or defer to the normal prompt
PostToolUseAfter a supported tool produces outputReview output, run checks
PreCompact / PostCompactAround context compactionPersist or restore state across a compaction
StopThe turn stopsRun validators (typecheck, lint, custom rules)

Every command hook receives one JSON object on stdin with at least session_id, transcript_path, cwd, hook_event_name, and model. Most turn-scoped events also carry permission_mode, whose documented values are default, acceptEdits, plan, dontAsk, and bypassPermissions.

Correction: Configured Is Not the Same as Trusted

The original version of this article said hooks are enabled by default and left it there. That is incomplete in a way that matters for anyone planning a rollout. Codex lists configured hooks before deciding which can run, and a non-managed command hook must be reviewed and trusted before it runs. Trust is recorded against the hook definition's current hash, so a new or edited hook is flagged for review and skipped until trusted. If hooks need review at startup, Codex prints a warning pointing you at /hooks.

The practical consequence: you cannot ship a security hook to a team by dropping it in a repo and assuming it is active. Either the developers trust it, or it arrives through a managed source. For one-off automation that already vets hook sources outside Codex, --dangerously-bypass-hook-trust runs enabled hooks without persisted trust for that invocation.

Known Caveats Today

The docs are explicit about a gap between what the framework parses and what currently runs:

  • Only type: "command" handlers execute. prompt and agent handlers are parsed in config but skipped at runtime.
  • Correction, August 21, 2026: async now works. This article previously said asynchronous command hooks were parsed but unsupported, which the docs said at the time. They are supported now; see "Background Hooks: A Limitation That Lifted" below.
  • Not every tool path is covered. PreToolUse and PostToolUse see shell commands (matched as Bash), unified exec, apply_patch (also matching Edit and Write), MCP tools by their mcp__server__tool name, and other local function tools. Hosted tools such as WebSearch do not use the local hook path at all, and write_stdin does not re-run PreToolUse for a command that already passed it.
  • Some output fields are parsed but inert. suppressOutput is parsed and not yet implemented; continue, stopReason, and suppressOutput are not supported on PreToolUse or PermissionRequest, and returning them there marks the hook run as failed while the tool call continues.

Update (August 28, 2026): The handler-type gap has narrowed. The hooks doc now says command and mcp_tool handlers are supported, with prompt and agent handlers still parsed but skipped. A type: "mcp_tool" handler calls a tool on an already-connected MCP server (required server and tool fields, optional input templates), runs synchronously, can block an operation when the tool returns a blocking decision, and is not supported on SessionEnd; so "build for command handlers today" below now reads "build for command and MCP tool handlers" (https://learn.chatgpt.com/docs/hooks).

The docs put the conclusion plainly: treat tool hooks as a useful guardrail, not a complete enforcement boundary. If you are designing a security or compliance posture around hooks, build for command handlers today and architect so additional handler types can plug in without re-doing the integration.

Background Hooks: A Limitation That Lifted

Until recently the hooks doc said the async option was parsed but that asynchronous command hooks were not supported. That is no longer true, and this article said otherwise for longer than it should have. Set async to true on a command handler and Codex continues while the hook runs:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.codex/hooks/post_tool_use.py",
            "async": true,
            "timeout": 120
          }
        ]
      }
    ]
  }
}

The equivalent inline config.toml form is async = true on the handler. Background hooks use the same input, matcher, trust review, timeout, and large-output handling as synchronous ones, and timeout is still in seconds with a 600 default.

What matters for design is when the output lands and what it can do:

  • Delivery is deferred, not immediate. If a turn is active, Codex finishes the current model request and tool calls, then makes the output available to the next model request in that turn. If no turn is active, it waits for the next user turn -- finishing a background hook does not start one.
  • Background hooks cannot decide anything. They cannot block, approve, rewrite, or otherwise control the operation that triggered them. additionalContext reaches the model and systemMessage surfaces as a warning; that is the whole of their influence. Tool policies, permission decisions, prompt rejection, and turn continuation still need synchronous hooks.
  • Eight at a time, per session. Additional matching hooks wait for a running one to finish, each invocation runs independently, and they can finish out of order.
  • Session end is a hard cut. Unfinished background hooks are cancelled and undelivered output is discarded. SessionEnd hooks always run synchronously.

The practical use is the slow, non-blocking work that used to force a choice between correctness and latency: pushing agent activity to an observability system, running an expensive scan whose result only needs to inform the next step, writing durable memory. Anything that must say no still belongs on the synchronous path.

Large Hook Output and Where It Goes

One more thing worth knowing before a hook starts returning real data. Codex limits each model-visible hook-output message to roughly 2,500 tokens. Past that it spills: the full text is written to <temp_dir>/hook_outputs/<session_id>/<uuid>.txt and the model receives a head-and-tail preview plus the saved path. If the file cannot be written, the model still gets a truncated preview.

additionalContextLimit on a handler changes that threshold -- omit it for the 2500 default, set a positive integer for a different one, or 0 to pass the handler's complete additional context straight to the model. The docs are blunt about the risk of that last option: context from multiple hooks and plugins adds up, and one hook with no cap can consume the entire context window. Because oversized output can land on disk, do not return secrets from a hook.

Enterprise Enforcement via requirements.toml

The enterprise lever is requirements.toml, where admins define managed hooks inline under a hooks table. That split is deliberate: the requirements file enforces the configuration while the actual scripts arrive through MDM or another device-management system. Managed hooks are trusted by policy and cannot be disabled from the user hook browser.

Two switches are worth knowing. To enforce managed hooks even for users who turned hooks off locally, pin [features].hooks = true in requirements.toml alongside the hooks table. Admins can force hooks off across the org the same way, with [features].hooks = false.

What Programmatic Access Tokens Solve

Hooks are the in-loop extensibility surface. Access tokens are the "is this Codex run actually you?" surface. Per the official access-tokens docs, Codex access tokens are ChatGPT workspace credentials scoped to Codex permissions that authenticate trusted non-interactive local workflows, including Codex CLI and app-server-based automation, with a ChatGPT workspace identity.

Concretely, that's the difference between an automated codex exec job depending on a developer's browser sign-in versus running under a credential the workspace issued and can revoke. The docs name the workflows:

  • codex exec jobs that run from trusted automation
  • Local scripts that need repeatable, non-interactive Codex CLI runs
  • Trusted app-server-based automation
  • Enterprise workflows where usage should be associated with a ChatGPT workspace user instead of an API organization key

The docs are also clear about when not to reach for one: if a Platform API key works for your automation, keep using API key auth. And if what you actually want is to trigger a published ChatGPT workspace agent from your own system, that needs a Workspace Agent access token, which is a different credential.

How Do You Use a Codex Access Token?

Two documented paths, and which one you want depends on whether the credential should persist on the machine.

For ephemeral automation, put the token in an environment variable and run Codex CLI normally:

export CODEX_ACCESS_TOKEN="<access-token>"
codex exec --json "review this repository and summarize the top risks"

For a persistent local login, pipe the token into codex login:

printf '%s' "$CODEX_ACCESS_TOKEN" | codex login --with-access-token
codex exec "summarize the last release diff"

codex login --with-access-token stores an agent identity credential in Codex CLI auth storage. If you would rather not persist credentials on the machine, use the environment variable instead.

codex app-server can use the same credential through either path to authenticate its OpenAI requests. One caveat the docs call out and that is easy to get wrong: that credential is separate from client-to-app-server transport authentication. A remote WebSocket connection needs its own bearer or capability token, and you should not reuse the Codex access token as the transport token.

Where Is the Codex Admin Console?

Access tokens live at chatgpt.com/admin/access-tokens. Three separate controls govern them, and they sit in different places:

ControlWhereWhat it does
Allow users to create access tokensWorkspace Settings, Permissions and roles, Access tokens sectionTurns on token creation for allowed members
Access token expiration limitWorkspace Settings, Permissions and roles, Codex Local sectionCaps the longest expiration a member may choose. Applies to new tokens only; existing tokens keep theirs
Allow members to use Codex LocalWorkspace Settings, Permissions and roles, Codex Local sectionGates local use in the ChatGPT desktop app, Codex CLI, and IDE extension

Creating a token is a short flow: open the Access tokens page, select Create, give it a descriptive name (the docs use release-ci and nightly-docs-check as examples), and choose an expiration. The docs recommend a finite window such as 7, 30, 60, or 90 days; the shortest custom expiration is one day, and if you pick No expiration you are expected to rotate on a schedule instead. Copy the token immediately -- you cannot view it again after closing the modal.

If the Access tokens page returns 404 or forbidden, that is the permission, not a bug: ask a workspace owner or admin to confirm your role includes token creation, and that Codex Local is enabled if your workflow needs it.

To rotate, the documented order is create the replacement, update the secret in the runner or secret manager, smoke-test with the new token, then revoke the old one. Owners and admins can revoke any workspace token; a member with the permission can revoke only tokens they created.

Correction: What the Permission Model Actually Says

An earlier version of this article read the docs' permission separation as meaning an automation token is a fresh, narrower permission surface that you provision per job. Re-checking the current doc, that is wrong, and it is wrong in the direction that makes a security design too optimistic.

What the doc actually says is that the workspace access token permission controls token creation, and that it "doesn't change a member's seat type, built-in workspace role, or local runtime permission profile." Separately, the token "represents the ChatGPT workspace user who created it, so runs can use that user's access and appear in workspace governance data." There is no per-token permission scoping documented. A token is closer to a long-lived stand-in for its creator than to a narrowly-scoped service credential.

That changes the design advice. You narrow a Codex access token by three levers, none of which is the token itself:

  • Owner. Create the token under an identity whose workspace access already matches the job. Do not mint a CI token from a broadly-privileged admin account.
  • Expiration. Prefer a finite window, and use the workspace expiration limit to stop members choosing forever.
  • The runner. The local permission profile on the machine executing codex exec is what bounds what the run can touch. That is where least privilege actually lives.

The docs' own risk list points the same way: a leaked token lets anyone start local runs as the token creator, and shared identities make audit trails hard to interpret, so tokens should be created for a specific workflow owner and used only on trusted runners. Public CI and forked pull requests are named explicitly as places tokens get exposed.

Correction, August 21, 2026: There Is a Non-Human Identity Now

Everything above is still true of a personal access token, the kind you create on the Access tokens page. But the paragraph this article ended that correction on -- if you need a credential whose permissions differ from a human's, this is not it -- has stopped being true, and it is worth saying that plainly rather than editing it away.

OpenAI now documents service accounts: non-human ChatGPT workspace identities intended for exactly the case this article said had no answer. Per the doc, a service account "represents a non-human workspace identity", while a personal access token "represents the workspace member who creates it". The access-tokens doc now points at it directly, distinguishing tokens created on the Access tokens page from "tokens created from a dedicated non-human workspace identity's detail page".

What a service account actually gives you:

  • Its own access, not its creator's. It can hold workspace roles and join groups like a member, and the doc is explicit that it "doesn't inherit the creator's permissions". Plugins are configured on the account itself and are not inherited either.
  • Tokens that represent the account. Create them from the account's detail page, confirm the Codex scope, choose an expiration. The full token appears once, as with personal tokens.
  • Delegated administration. Only workspace owners and admins can create, delete, or share accounts. Sharing assigns one of three roles to people or groups -- User can create the account's tokens but not configure it, Configure is the reverse, and Manager does both.
  • SCIM provisioning, by setting userType to ServiceAccount in the identity provider. SCIM-managed accounts cannot be renamed or deleted inside ChatGPT.

Two constraints to check before planning around them. Service-account access tokens require Codex CLI 0.142.0 or later, and service accounts are documented as available only on pay-as-you-go plans. Usage is otherwise the same as any other access token: CODEX_ACCESS_TOKEN for ephemeral runners, codex login --with-access-token on a trusted machine.

So the design advice splits rather than reverses. For a CI job that should not be anybody's account, a service account is now the right primitive. For everything still running on a personal token, the three levers above -- owner, expiration, and the runner's permission profile -- remain the only ones you have.

Token Hygiene

The docs spell out the standard list, and it's worth quoting in working form:

  • Store tokens in a secret manager. Never inline them in a script.
  • Keep tokens out of logs (including CI logs, especially failed-build artifacts).
  • Rotate on a schedule. Don't let any single token outlive its useful lifetime.
  • Prefer finite expirations over indefinite ones.
  • Tie tokens to the narrowest workflow that needs them; don't share one token across unrelated automations.

How a Reader Uses This

Two concrete shapes:

Pattern 1: Secret-Scan Hook + CI Token

A platform team that wants developers to use Codex but is worried about leaked credentials:

  1. Author a UserPromptSubmit hook that scans prompts for high-confidence credential patterns (API keys, OAuth refresh tokens, SSH private keys) before they reach the model.
  2. Enforce it as a managed hook in requirements.toml, and pin [features].hooks = true there so it stays active even for developers who turned hooks off locally. Managed hooks skip the trust-review step that would otherwise leave a repo-local copy inert.
  3. Provision an access token for the CI job that runs nightly codex exec validation against the main branch. If the workspace is on a pay-as-you-go plan and its runners are on Codex CLI 0.142.0 or later, create it from a service account so the job is not attached to any person; otherwise create it under the individual identity that should own that job, never an admin's.
  4. Bound the job on the runner, not on the token: a token carries its creator's workspace access, so the CI machine's permission profile and expiration limit are the real controls. Keep it on a trusted runner -- never one that builds forked pull requests.

Pattern 2: Per-Repo Memory + Validation

A team with multiple repos that want different agent behavior in each:

  1. Put a <repo>/.codex/hooks.json in each repo with a SessionStart hook that loads repo-specific prompts and policies. Note the prerequisite: project-local hooks load only when that project's .codex/ layer is trusted, and each hook still needs a one-time trust review.
  2. Add a Stop hook that runs the repo's preferred validator (typecheck, lint, test) and surfaces failures back to the agent.
  3. Add a SessionEnd hook that writes the day's work to a memory file so the next session resumes with context. Budget for its timeout: SessionEnd defaults to 1 second and supports a maximum of 3.
  4. Resolve hook commands from the git root rather than a relative .codex/hooks/... path -- Codex may be started from a subdirectory.
  5. None of this requires programmatic tokens. This is all interactive-session extensibility.

When to Reach for Access Tokens Instead of Just Hooks

You want to...HooksAccess tokens
Modify in-session behavior (validators, scanners, memory)YesNo
Enforce org-wide rules across interactive sessionsYes (via requirements.toml)No
Run Codex from a CI pipelineMaybe (hooks still apply)Yes -- needed for non-interactive auth
Run scheduled codex exec jobs as a serviceNoYes
Audit which automation ran which Codex actionNoYes -- usage ties back to workspace

How This Fits With the Recent Codex Surface Expansion

OpenAI has been moving Codex onto more surfaces and into more workflows. The pattern across recent months:

The earlier releases shipped the CLI-level affordances (lifecycle hooks, headless entry point). This is the part where OpenAI tells developers how the automation surface is intended to be used, with enterprise-grade auth attached.

Caveats

  • Handler-type gap. Only type: "command" handlers run today; prompt and agent handlers are parsed but skipped. Don't design critical paths around handler types that aren't executing yet.
  • Background hooks are informational only. async: true works now, but a background hook cannot block, approve, rewrite, or continue anything. Keep every enforcement decision on a synchronous hook.
  • Tool-path coverage. Hooks intercept shell, unified exec, apply_patch, MCP tools, and other local function tools, but not hosted tools such as WebSearch. The docs' own framing: a useful guardrail, not a complete enforcement boundary.
  • Trust gate. A non-managed command hook does nothing until it is reviewed and trusted, and editing it re-arms the review. Only managed sources are trusted by policy.
  • Business/Enterprise only. Access tokens require a ChatGPT Business or Enterprise workspace. Individual Pro/Plus users do not get them.
  • No per-token scoping on a personal token. It carries its creator's workspace access; you narrow it by owner, expiration, and the runner. If a Platform API key would do the job, the docs say to use one.
  • A non-human identity exists, with conditions. Service accounts hold their own roles, groups, and tokens, but they need Codex CLI 0.142.0 or later and are documented as pay-as-you-go plans only. Confirm both before designing a rollout around them.

Update (August 28, 2026): The handler-type gap above is smaller now: command and mcp_tool handlers run, while prompt and agent handlers remain parsed but skipped. MCP tool hooks run synchronously and are not supported on SessionEnd (https://learn.chatgpt.com/docs/hooks).

FAQ

See structured FAQ in the schema header for question-level details: what hooks do, which handlers run today, whether a hook can run in the background, whether hooks run without being trusted, how enterprise enforcement works, what access tokens are, whether a credential exists that is not tied to a person, how to use one in CI, where the admin console is, and how the permission model actually works.

Corrections and Updates

August 21, 2026: Two limitations this article carried are no longer limitations, and both were negative claims -- the kind that decay silently, because nothing about the sentence starts looking wrong.

July 28, 2026: Both docs have grown substantially since this article first published on May 15, 2026, and they have since moved hosts: developers.openai.com/codex/hooks and developers.openai.com/codex/enterprise/access-tokens redirect to learn.chatgpt.com/docs/hooks and learn.chatgpt.com/docs/enterprise/access-tokens.

Sources

Every hook event, handler-type limitation, permission control, and expiration figure above comes from the three OpenAI docs listed first, each re-fetched and checked on 2026-08-21; the August 21 corrections to async support and to the non-human-identity claim come from the same fetch. Codex hooks and access tokens were first flagged in a May 2026 OpenAI Developers post on X; that post is not cited here and nothing on this page rests on it, because x.com answers automated requests with HTTP 200 and a JavaScript shell containing none of the post text, re-checked August 31, 2026, and a claim sourced only there cannot be re-checked.

Related coverage

Frequently Asked Questions

What did OpenAI ship for Codex automation?

Two capabilities, both documented on OpenAI-owned surfaces. Hooks are an extensibility framework that injects scripts into the Codex agent loop at eleven named lifecycle events -- session start and end, prompt submission, tool calls, permission requests, context compaction, and turn stop. Programmatic access tokens are ChatGPT Business and Enterprise workspace credentials, created in the ChatGPT admin console, that authenticate non-interactive Codex CLI and app-server runs, with finite expirations and revocation.

What are Codex hooks?

Hooks are an extensibility framework for Codex. You inject scripts (or, as of August 2026, calls to tools on an already-connected MCP server) into the agentic loop at eleven lifecycle events, from SessionStart to Stop. Hooks are enabled by default and configured in hooks.json or inline in config.toml at the user, project, or plugin layer; the /hooks command inspects, trusts, or disables them.

What hook handlers actually run today?

As of August 2026, command and mcp_tool handlers run; prompt and agent handlers are parsed but skipped. At launch only command handlers ran. An mcp_tool handler calls a tool on an already-connected MCP server, runs synchronously, and is not supported on SessionEnd. Asynchronous command hooks also run via async true. Hosted tools such as WebSearch skip the local hook path.

Can a Codex hook run in the background?

Yes, as of the current docs. Set async to true on a command handler and Codex continues while the hook runs. Codex runs up to eight background hooks concurrently per session, delivers their output at the next safe point in the conversation, and cancels unfinished ones when the session ends. Background hooks cannot block, approve, rewrite, or otherwise control the operation that triggered them, and SessionEnd hooks always run synchronously.

Is there a Codex credential that is not tied to a person?

Yes. Service accounts are non-human ChatGPT workspace identities with their own roles, groups, and plugins, created by workspace owners and admins at chatgpt.com/admin/service-accounts. Tokens created from a service account's detail page represent the account rather than the person who created it. Service-account access tokens require Codex CLI 0.142.0 or later and are available only on pay-as-you-go plans. A personal access token created on the Access tokens page still represents its creator.

Do Codex hooks run automatically once configured?

No. Hooks are enabled by default as a feature, but a non-managed command hook must be reviewed and trusted before it runs. Codex records trust against the hook definition's current hash, so a new or edited hook is marked for review and skipped until you trust it in /hooks. Managed hooks from system, MDM, cloud, or requirements.toml sources are trusted by policy and cannot be disabled from the user hook browser.

How are enterprise hooks managed?

Enterprise-managed hooks are defined inline under a hooks table in requirements.toml, which is useful when admins want to enforce the configuration while delivering the scripts through MDM. To enforce managed hooks even for users who turned hooks off locally, admins pin the hooks feature flag to true in requirements.toml alongside the hooks table. Admins can also force hooks off the same way.

What are Codex programmatic access tokens?

Codex access tokens are ChatGPT workspace credentials scoped to Codex permissions that authenticate non-interactive local workflows, including Codex CLI and app-server automation. They are currently supported for ChatGPT Business and Enterprise workspaces. Use them for codex exec jobs, repeatable local scripts, trusted app-server automation, and enterprise workflows where usage should tie back to a workspace user rather than an API organization key.

How do you use a Codex access token in CI?

Two documented paths. For ephemeral automation, put the token in the CODEX_ACCESS_TOKEN environment variable and run Codex CLI normally. For a persistent local login, pipe the token into codex login --with-access-token, which stores an agent identity credential in Codex CLI auth storage. The codex app-server can use the same credential, but the docs say not to reuse a Codex access token as the WebSocket transport token.

Where is the Codex admin console for access tokens?

Access tokens live at chatgpt.com/admin/access-tokens. The permission that governs them is in Workspace Settings, Permissions and roles, under the Access tokens section as Allow users to create access tokens. The maximum expiration members may choose is set separately as Access token expiration limit in the Codex Local section of the same page. If the tokens page returns 404 or forbidden, the permission is not enabled for your role.

How are access-token permissions managed?

The workspace access token permission controls who may create tokens; it does not scope what a token can do. A personal access token represents the ChatGPT workspace user who created it, so runs use that user's access and appear in workspace governance data. The separate Allow members to use Codex Local permission gates local client use. You narrow a personal token by choosing its owner, its expiration, and the runner's own permission profile -- not by scoping the token itself. If the owner should not be a person at all, use a service account, which is a workspace identity in its own right with its own roles and groups.

Get the weekly AI Catchup

Tools, practices, and what matters, in your inbox every week.