How to Configure Codex with AGENTS.md for C# and .NET Projects
Create concise, accurate repository guidance with real build commands, scoped conventions, architectural boundaries, and review evidence.
Prepare one small working guide for the real Jovenzo.Samples solution: its four projects, exact build and test commands, and the contracts a change must preserve. The downloadable AGENTS.example.md stays passive until you deliberately adopt it in a separate working copy.
This exercise starts with a read-only inventory and an existing calculator test, rather than adding a feature the package already implements. It separates three questions: do the instructions describe real files, do their commands work, and what did a particular Codex run actually load? Those questions need different evidence. A successful .NET test run cannot answer the last one.
Understand the role of AGENTS.md
A useful guide removes recurring ambiguity. In this package, “run the tests” leaves the working directory, project and configuration unspecified. The guide instead names Jovenzo.Samples.slnx, its Release build and the shared test project. It also says when Node tests are relevant and how a final archive check differs from a focused development check.
The official AGENTS.md documentation is the source for discovery behavior, summarized below. The package itself supplies the project facts. Its filename remains AGENTS.example.md in the download.
Stable commands belong in the guide, while a task supplies the requested outcome. Asking for a source inventory does not authorize a framework migration, live provider call or publication. Conversely, an old guide should not silently redefine a new task. The file helps an assistant navigate the project; permissions and the user's actual request still govern what work can be done.
Inspect the repository before writing instructions
Extract the shared sample archive and locate the directory containing README.md and Jovenzo.Samples.slnx. That directory is the solution root used by every command below. Core holds direct provider adapters, PDF/retrieval code and bounded tools. Api owns HTTP endpoints and browser pages. Sdk contains provider-selection, agent and MCP console paths. Tests is the common offline test project.
# Run in the extracted Jovenzo.Samples directory.
Get-Location
rg --files -g '*.slnx' -g '*.csproj' -g 'Directory.Build.*' -g 'global.json'
rg --files -g '*Tests.cs' -g '*test.mjs' -g 'README.md' -g 'AGENTS*'
The inventory should find four csproj files and one slnx file. Directory.Build.props targets net10.0 and enables nullable references, implicit usings, warnings as errors and package lock files. No global.json is bundled. A target framework selects the API surface/runtime target; it does not pin the installed SDK used by the build. Record the actual SDK with dotnet --version instead of claiming a missing file chose it.
Working directory is an observable part of a command. From tests/Jovenzo.Samples.Tests, running dotnet build Jovenzo.Samples.slnx -c Release --no-restore produced MSB1009 because that relative solution path does not exist there. The solution was not broken. Returning to the solution root fixed the path:
# Starting in tests/Jovenzo.Samples.Tests:
Set-Location ../..
dotnet restore Jovenzo.Samples.slnx --locked-mode
dotnet build Jovenzo.Samples.slnx -c Release --no-restore --disable-build-servers -m:1
The dotnet test reference distinguishes runner-specific options. This guide uses the existing sample test project and its VSTest setup, not a new runner configuration.
An explicit relative path is another option: from that same test directory, ../../Jovenzo.Samples.slnx names the solution. The guide chooses a consistent root convention so subsequent commands do not mix two reference points. It also records the current directory in the handoff, making a path error distinguishable from a compiler failure.
Write a concise root guide
The following is the complete downloadable AGENTS.example.md, not a generic alternative or selected excerpt. The project paths and commands match the shared archive. README.md retains detailed setup and live-service requirements; this short guide concentrates on navigation, boundaries and evidence.
# Jovenzo.Samples working guide
Passive template: review before adopting as AGENTS.md in a separate working copy.
All paths and commands below are relative to the directory containing Jovenzo.Samples.slnx.
## Project map
- src/Jovenzo.Samples.Core: direct HTTP adapters, retrieval, PDF processing and bounded tools.
- src/Jovenzo.Samples.Api: JSON/SSE/PDF endpoints and browser clients.
- src/Jovenzo.Samples.Sdk: provider selection, agents, MCP and console workflows.
- tests/Jovenzo.Samples.Tests: shared offline C# tests; tests/stream-browser.test.mjs: browser-module tests.
## Verification
Start at the solution directory. From tests/Jovenzo.Samples.Tests, `Set-Location ../..` returns there in PowerShell; otherwise use the correct explicit project path.
```powershell
dotnet restore Jovenzo.Samples.slnx --locked-mode
dotnet build Jovenzo.Samples.slnx -c Release --no-restore --disable-build-servers -m:1
dotnet test tests/Jovenzo.Samples.Tests/Jovenzo.Samples.Tests.csproj -c Release --no-build --no-restore
```
Rebuild Release after source edits before using --no-build. For a focused calculator check after that build:
```powershell
dotnet test tests/Jovenzo.Samples.Tests/Jovenzo.Samples.Tests.csproj -c Release --no-build --no-restore --filter "FullyQualifiedName~Jovenzo.Samples.Tests.DiscountCalculatorTests"
```
For JavaScript changes, and for the final shared-package check:
```powershell
node --test tests/stream-browser.test.mjs
```
The final shared-package check repeats locked restore, Release build, all C# tests and Node tests from a separate ZIP extraction. README.md gives prerequisites. net10.0 is the target framework; no global.json pins the SDK here.
## Boundaries and handoff
- IAiAnswers serves direct text/SSE answers; IGroundedAnswers serves grounded generation; ITextEmbeddings serves embeddings. SDK provider selection uses IChatClient separately.
- Preserve Ai/text, endpoint paths, delta/done/error payloads, cancellation, resource limits and safe errors. The store:false rule belongs to the direct OpenAiResponsesClient request, not every SDK integration.
- Keep changes within the requested scope. Framework/package/database/publication changes need task justification; this guide does not authorize them.
- Credentials stay outside committed files. Offline tests use fixtures, not paid calls. Tenant authorization and CI are production work, not implemented guarantees here.
- Package only source/documentation/tests: no secrets, bin/obj, session logs or experiment output.
- Report working directory, exact commands and actual outcomes. Name blocked/unrun checks explicitly; never turn a recommendation or model summary into execution evidence. These instructions do not replace permissions, sandboxing or code review.
The focused calculator command is appropriate for this article's small exercise. It does not replace the full suite when preparing the shared package. JavaScript changes need the actual browser-module tests; the final archive check runs those tests even when this particular task changed only documentation. A report should identify the selection rather than presenting ten calculator cases as all shared C# tests.
Adoption happens in a separate working copy, not in the main publication checkout. After reviewing the file, this PowerShell guard creates AGENTS.md only when it is absent. If a guide exists, compare and merge intentionally; do not overwrite it with a downloaded template. The copy operation also refuses an existing destination.
# In your separate extracted Jovenzo.Samples copy:
if (Test-Path -LiteralPath AGENTS.md) {
Write-Output 'Compare AGENTS.example.md with AGENTS.md and merge the intended rules.'
} else {
[System.IO.File]::Copy(
(Resolve-Path -LiteralPath AGENTS.example.md).Path,
(Join-Path (Get-Location).Path 'AGENTS.md'),
$false)
}
The downloaded filename is absent from default discovery names; merely extracting it does not activate it. A user-customized fallback list could change that assumption, so record the environment used for a discovery experiment rather than promising identical behavior in every profile.
Use scope deliberately
OpenAI documents the following startup chain for Codex runs:
- Global guidance comes from CODEX_HOME, defaulting to ~/.codex; the first nonempty override or normal file is used.
- Project discovery walks from the project root, usually the Git root, to the starting directory. Without a project root, only the current directory is checked.
- Each directory contributes at most one nonempty file: AGENTS.override.md, then AGENTS.md, then configured fallback names in order.
- Ancestor guidance is combined before more local guidance; unrelated sibling directories are not a startup sweep.
- The combined project-guidance budget is project_doc_max_bytes, 32 KiB by default. Empty files are skipped.
- Start a new run/session after changing files or discovery configuration.
These are documented rules, not claims that every combination was exercised here. The observed CLI trial below covers selected root/nested cases. It does not establish discovery in GitHub code review, an IDE integration or another coding assistant.
An extracted ZIP has a solution directory but does not necessarily have a Git root. Starting Codex inside its test folder is therefore different from starting inside a cloned repository. For an isolated exploration, extract outside an existing checkout, initialize that copy as its own temporary repository, and verify the reported root before launching Codex:
# Only in the separate copy selected for the experiment:
git init
git rev-parse --show-toplevel
The trial used this temporary layout. The active filenames shown here are experiment fixtures only; none is shipped as active guidance or added to the real repository. The diagram above illustrates possible placement, not a pre-existing hierarchy in the application.
Jovenzo.Samples/ # Independent temporary Git root
.git/
AGENTS.example.md # Passive downloadable guide
AGENTS.md # Adopted guide plus a harmless trial marker
src/Jovenzo.Samples.Sdk/
AGENTS.md # Unrelated sibling marker
tests/
AGENTS.md # Deliberately shadowed marker
AGENTS.override.md # Local marker
Jovenzo.Samples.Tests/ # Codex starting directory
A directory listing only establishes that files exist. It does not establish that they were selected. In this trial, listing AGENTS.md filenames without looking for overrides caused the model's final summary to name the wrong local source. The initial session context supplied stronger evidence, as described in the verification section.
Specify the .NET conventions that prevent real defects
“Preserve the API contract” becomes reviewable when it names an actual field. The JSON answer routes accept text, not question. Their SSE application events are delta, done and error; successful deltas contain a text string, done contains null text, and errors carry a safe code. A documentation task should not rename these contracts or revise limits simply to match an illustrative guide.
The interfaces also have distinct jobs. IAiAnswers covers direct text answers and streaming; IGroundedAnswers covers generation with supplied grounding context. ITextEmbeddings supplies vectors. The SDK provider command instead uses Microsoft.Extensions.AI's IChatClient, wrapped by ExplanationService. Describing all integration as IAiAnswers would send a future task to the wrong seam.
OpenAiResponsesClient puts store:false in its direct Responses request. This is a narrow implementation rule, not a blanket promise about SDK chat, agent or embedding requests. The API integration guide explains that direct path; the agent guide discusses a different composition. Accurate instructions preserve those differences.
The example mentions cancellation, bounds and safe errors because those protections exist in the package. It does not announce a tenant identity system, deployed CI or production authorization. The sample's localhost controls and deterministic fixtures are useful teaching boundaries; they cannot be renamed into production guarantees by an instruction file.
Pair durable guidance with a concrete task
A small inventory task gives the reader something observable without inventing a feature request. Cancellation is already present in the streaming example, so asking to add it again would invite needless changes. Start by locating the existing calculator and its test class, then run the existing focused selection after the required Release build.
Inventory Jovenzo.Samples without editing source or instructions.
Report the solution directory and the four project paths.
Locate DiscountCalculator.cs and DiscountCalculatorTests.cs.
Read the applicable guidance; distinguish loaded sources from files merely present.
From the solution root, perform the documented locked restore and Release build,
then run the existing DiscountCalculatorTests selection.
Report the actual commands, directory, result and any blocked checks.
Do not add tests, change production behavior or invoke a live AI provider.
This reader exercise permits build output while keeping source unchanged. It differs from the strictly read-only Codex discovery trial, which did not run builds or tests. The .NET commands need an installed SDK and restore access; running Codex additionally needs a ready, authorized account, connectivity and available usage. Those are separate prerequisites, not an API key requirement for the calculator.
The OpenAI workflow cookbook provides broader iterative-development context. This package needs no new planning framework to perform the inventory. Keep the task small enough to compare its requested action with command records and the final source diff.
Verify that the guide helps
Verification A checks paths and commands. The map was compared with the real solution, all guide paths exist, and its root commands were executed. The wrong-directory failure was reproduced deliberately, then corrected before the successful build and tests. The adoption guard was checked separately so an existing guide was preserved.
Verification B checks actual Codex discovery. A ready ChatGPT-authenticated CLI, version 0.166.0-alpha.5.1, ran one inventory-only task from the temporary tests/Jovenzo.Samples.Tests directory with a read-only sandbox. The existing profile was reused without changing its configuration or creating credentials. No global AGENTS.md or AGENTS.override.md was present. The CLI's command reference documents the execution options; this trial did not disable permissions or sandbox controls.
| Evidence | Actual observation | Limit |
|---|---|---|
| Session context before the first assistant response | Root and tests-override fixture markers present; shadowed normal and sibling markers absent | Selected local cases, not every discovery setting |
| Executed command events | Two successful read-only inventory commands; no build or test invocation | Does not establish the later .NET results |
| Model's final source summary | Incorrectly named tests/AGENTS.md instead of tests/AGENTS.override.md | The summary alone was unreliable evidence |
Only sanitized version, directory, source names and fixture-presence results belong in the technical report. Raw session records and personal instructions are not copied into the archive. The observed source-attribution error remains part of the result; one trial cannot establish perfect adherence or an instruction-effectiveness success rate. Global overrides, custom fallbacks, a missing Git root, size-limit truncation, restart behavior and other Codex surfaces were not experimentally verified.
Keep permissions and untrusted content separate
The guide cannot enforce its own security boundaries. An instruction saying credentials stay outside committed files is useful, but actual secret handling and access restrictions remain separate mechanisms. No key or connection string is needed for the inventory or offline tests. The discovery trial used the already authorized Codex environment rather than asking the reader to generate a credential for an unrelated model request.
Logs and third-party text can contain imperative language without becoming project policy. A copied AGENTS.example.md is likewise a reviewable template until deliberately adopted.
Instructions also do not grant permission to force-push, publish, reset data or change an account. Keep the scope of those actions in the actual task and enforce access through the environment. Neither a useful guide nor a passing test suite replaces code review, CI or a production security assessment.
Maintain the guide like an interface
A guide change should be checked against the affected files. If the test project moves, update its command and rerun it from the documented directory. If a new adapter is added, describe its actual interface rather than extending an old rule to every integration. Delete obsolete assumptions instead of accumulating exceptions under a generic architecture slogan.
The handoff should separate execution from recommendation. “Node tests are recommended” means they did not run; “45 passed” requires a completed run and its output. A blocked command needs its working directory and relevant failure. The same standard applies to discovery: a model's statement about a loaded filename is weaker than a session record containing the fixture guidance before any tool read.
Verification results — November 2, 2026
Package revision agents-guide-1, based on 639c475 plus these documentation changes: the guide's paths and commands were checked against the real four-project package. Locked restore and Release build succeeded with zero warnings or errors. Fresh runs passed 226 C# tests, including the selected 10 calculator cases, and 45 JavaScript tests, with no failures or skips. Application code, tests and package versions are unchanged.
The final ZIP was extracted separately: locked restore and all four Release builds succeeded with zero warnings or errors; fresh extracted runs passed 226 C# tests, the selected 10 calculator cases and 45 JavaScript tests. The archive contains 45 source/documentation/test files; SHA-256: d7b1507114d17496c9523982cac9e212f30a436c45e4e703b7a632c880629441. The separate CLI trial confirmed selected guidance in its initial session context but also exposed the final summary's incorrect local filename. It was not a reliability benchmark. No sample-provider request, production deployment, GitHub review-discovery test or other-tool compatibility test was performed.
Key takeaways
- The copyable guide describes the real four-project solution and stays passive in the ZIP.
- Working directory, command selection and exact outcomes make verification reproducible.
- Documented discovery rules and a particular CLI trial are separate evidence.
- Source guidance helps navigation; permissions and production controls remain independent.
Frequently asked questions
Is AGENTS.example.md active after extraction?
Not under default filename discovery. Review it and adopt it deliberately in a separate copy; compare rather than overwrite an existing AGENTS.md.
Does a successful build prove Codex loaded the guide?
No. It proves a command completed. This revision checked discovery separately and compared session-context evidence with the model's imperfect summary.
Will another assistant behave the same way?
That was not tested. The documentation-based tool comparison describes a separate evaluation approach without establishing identical behavior.
Conclusion and next step
You now have a passive guide that matches Jovenzo.Samples, a safe adoption step, tested root commands and a small inventory exercise. Start with that exercise in a separate copy, record what actually ran, and check discovery evidence before trusting a source summary. Update the guide when its commands or boundaries change.
