Skip to main content
Codex Tutorial: OpenAI's Coding Agent in Depth

Writing a Task Codex Can Act On

A good Codex task is specific, scoped to one logical change, includes examples if needed, and describes success criteria -- not a vague wish list.

Beginner10 minBy ToolDix Editorial

Learning objectives

  • Write a task description that Codex can disambiguate and execute
  • Scope a task to a single, reviewable change
  • Provide enough context that Codex succeeds without a retry loop

ToolDix original visual

Codex Tutorial practice loop
1

Frame

Name the outcome and constraints.

2

Build

Try one bounded workflow.

3

Review

Keep evidence, revise, and share.

The anatomy of a good task

A good task has four parts: a clear goal, a scope boundary, success criteria, and any examples or constraints Codex needs to follow your project's conventions.

Goal: "Add a cache layer to database queries" is clear; "make the database faster" is not. Codex needs to know what you're doing, not what outcome you want. Outcomes are ambiguous (do you want caching, pagination, query optimization, or all three?), but actions are concrete.

Scope: "In the database.ts module, wrap all SELECT queries in a cache function" is scoped; "improve our data layer" is not. Codex should know which files to touch and which to leave alone. A good scope is something you could merge as a single PR.

Success criteria: "The cache should return stale data within 30 seconds if a fresh query would take longer than 100ms" tells Codex what "working" means. Without this, Codex might write a cache that never evicts, or one that's slower than the original queries.

Conventions and constraints: "Follow the pattern in auth.ts for initialization" or "don't import lodash" gives Codex guardrails. Your project probably has patterns; naming it saves Codex from inventing its own style.

Scope and clarity matter more than the model

ToolDix original diagram
Vague task vs. well-scoped task
Vague task
"Add error handling"
"Make it faster"
"Improve maintainability"
Codex guesses and often guesses wrong. Requires revisions.
Well-scoped task
In payment.ts, wrap stripe.charge() in try-catch
Cache SELECT queries with 5-min TTL in database.ts
Extract JWT validation into separate function
Codex knows exactly what to do. High first-try success.

Good task, bad task

Bad task: "Add error handling."

Why it's bad: Error handling can mean try-catch blocks, error codes, logging, graceful degradation, user-facing messages, or recovery logic. Codex will guess and probably guess wrong.

Good task: "In payment-processor.ts, wrap the stripe.charge() call in a try-catch block. If it fails, log the error with the full error object and the customer ID, then return a 500 status with an error message. Follow the pattern in invoice-handler.ts for the error format."

Why it's good: Codex knows the file, the specific function, what kind of error handling (try-catch), what to do in the catch block (log and return), and an example of your convention to follow.


Bad task: "Refactor the auth module to be more maintainable."

Why it's bad: "Maintainable" is subjective. Does Codex refactor to smaller functions? Use more comments? Change variable names? Add types? Extract constants? It has no objective measure.

Good task: "In auth.ts, extract the JWT validation logic into a separate validateToken() function. It should accept a token string and return {valid: boolean, decoded?: JwtPayload}. Use TypeScript types to match the existing JwtPayload interface. Tests should verify that valid tokens decode correctly and invalid tokens return {valid: false}."

Why it's good: Specific files, specific logic to extract, specific return type, a naming convention (validate, Payload), and concrete test cases.


Bad task: "Optimize this code for performance."

Why it's bad: Codex doesn't know which performance metric matters (latency? memory? throughput?), which code, or what "optimized" means (1x faster, 10x faster?).

Good task: "The filterCustomers() function in queries.ts is O(n²) because of nested loops. Refactor it to O(n log n) using a hash map. The function should return the same result but process 10,000 customers in under 500ms on a standard laptop. Write a performance test that verifies this."

Why it's good: Specific algorithm problem identified, specific data structure hinted (hash map), concrete performance target (500ms for 10k items), and testable.

A worked example: building a task step by step

You notice that your API routes have inconsistent return types for errors. Some return {error: string}, others return {message: string}. You decide to standardize on {error: string, code: string}. Here's how to write the task:

First draft: "Make error returns consistent."

Too vague. Codex could change format, add data, or do something you didn't intend.

Second draft: "In the /routes directory, make all error responses return {error: string, code: string} instead of {message: string}."

Better, but Codex might not know what code should be (HTTP status code? a domain-specific error code?).

Final draft: "In /routes, update all error responses to use the format {error: string, code: string}, where code is one of the values in the ErrorCode enum from types.ts. Keep the HTTP status code the same; just change the response body. Update the TypeScript return types in each route to match. Reference routes/health.ts for the pattern."

This task is specific, scoped, and includes a reference. Codex knows exactly what format to use, where to find the enum, which types to update, and has a concrete example. It can succeed on the first try.

Common mistake

Writing tasks that try to combine multiple logical changes. "Add a cache layer and switch from polling to WebSockets" is two tasks. Codex will either do both poorly or pick one and ignore the other. Break it into "Add a cache layer to reduce database hits" and "Switch from polling to WebSocket subscriptions for real-time updates" -- two separate tasks, two separate diffs, easier to review and revert if one doesn't work out.

Sources and license context

These references informed the lesson. ToolDix adds its own explanation, workflow, and practice rather than reproducing source material. Every link below leaves ToolDix and opens the publisher's own site in a new tab.

Keep going

Read these next on ToolDix.

Original lessons that build on what you just read.