Instruction file imported from NVIDIA/NeMo-Agent-Toolkit (
.cursor/rules/general.mdc). Copyright stays with the author.
NeMo Agent Toolkit General Coding Guidelines
These are the overarching standards that every source, test, documentation and CI file in this repository must follow. Adhering to these rules locally ensures the project's automated checks and pipelines succeed on your first push.
Terminology and Naming
- Make sure to follow this naming convention for all the documentation. If there is any documentation not following this rule, you MUST update it.
- Full name (first use): "NVIDIA NeMo Agent Toolkit" — use for document titles, webpage headers, and any public descriptions
- Short name (subsequent references): "NeMo Agent Toolkit" or "the toolkit"
- Capitalization rules:
- In document titles, headings, or any context where all words are capitalized, use "Toolkit" (capital T): e.g., "NVIDIA NeMo Agent Toolkit" or "NeMo Agent Toolkit"
- In all other contexts (body text, descriptions), use "toolkit" (lowercase t): e.g., "NVIDIA NeMo Agent Toolkit" or "NeMo Agent Toolkit"
- Technical identifiers (code, CLI, packages, URLs):
natfor the API namespace and CLI toolnvidia-natfor the package nameNAT_prefix for environment variablesNeMo-Agent-Toolkitfor URLs, directory names, and contexts where capitalization is preserved (no underscores or spaces)
- "NAT" abbreviation:
- OK in code comments
- NEVER use "NAT" or "nat" to refer to the toolkit in documentation
- Examples:
- "In the NeMo Agent Toolkit, you can…"
- "Change directory to the NeMo Agent Toolkit repo root…"
- Heading: "# Getting Started with NeMo Agent Toolkit"
- Consistently use this terminology throughout all documentation
- NeMo Agent Toolkit was previously known as the Agent Intelligence toolkit, and AgentIQ. You should NEVER use the deprecated names, including Agent Intelligence toolkit, aiqtoolkit, AgentIQ, or AIQ/aiq. If you see any of these names in the documentation, you should update it based on the latest naming convention above, unless those names are intentionally used to refer to the deprecated names, or implementing a compatibility layer for the deprecated names.
- DO NOT change the content of
CHANGELOG.md - AIQ Blueprint is the intended name for the blueprint. DO NOT change it.
Project Structure
- All importable Python code lives under
src/orpackages/<pkg>/src/so namespace-packages resolve correctly. - Each example is an installable package in
examples/<example_name>and exposes an__main__.pyforpython -m <example_name>execution. - Examples directory guidelines:
- At minimum, examples should contain a
README.mdorREADME.ipynbfile. - Python code should be placed in a
src/subdirectory with apyproject.tomlfile. - Scripts should be placed in a
scripts/subdirectory (optional). - YAML files should be placed in a
configs/subdirectory. - Sample data files should be placed in a
data/subdirectory and checked into git-lfs.
- At minimum, examples should contain a
- Packages directory guidelines:
- Each package should contain a
pyproject.tomlfile. - The
pyproject.tomlshould declare a dependency onnvidia-nator another package with a name starting withnvidia-nat-. - Dependencies should use
~=<version>format with two-digit versions (e.g.,~=1.0). - If packages contain Python code, they should have tests in a
tests/directory at the same level aspyproject.toml.
- Each package should contain a
- Unit tests live in
tests/(orexamples/*/tests) and use the markers defined inpyproject.toml(e.g.integration). - Documentation sources are Markdown files under
docs/source. Image files should be placed indocs/source/_staticdirectory. - Configuration files consumed by code are stored next to that code in a
configs/folder. - Large / binary assets must be committed with Git-LFS and placed in a neighbouring
data/folder. - Shell or utility scripts belong in
scripts/orci/scripts/– never mix them with library code. - Source code organization:
packages/nvidia_nat_core/src/nat/**/*: Contains core functionality. Changes should prioritize backward compatibility.
Code Formatting & Imports
- Follow PEP 20 and PEP 8 for Python style guidelines.
- Run yapf second (PEP 8 base,
column_limit = 120). - Indent with 4 spaces, never tabs, and ensure every file ends with a single newline.
- CI fails if formatting is wrong; run
pre-commit run --all-fileslocally before pushing.
Linting
- ruff (via
ruff check --fix) also runs via pre-commit; is executed using the configuration embedded inpyproject.toml, fix warnings unless they're explicitly ignored inpyproject.toml. ruff is only used as a linter not for formatting. - Respect the naming schemes:
snake_casefor functions & variables,PascalCasefor classes,UPPER_CASEfor constants.
Type Hints
- All public APIs require Python 3.11+ type hints on parameters and return values.
- Prefer
collections.abc/typingabstractions (Sequenceoverlist). - Use
typing.Annotatedfor units or extra metadata when useful. - Treat
pyrightwarnings (configured inpyproject.toml) as errors during development.
Exception Handling
- Preserve stack traces and prevent duplicate logging when handling exceptions.
- When re-raising exceptions: use bare
raisestatements to maintain the original stack trace, and uselogger.error()for logging (notlogger.exception()) to avoid duplicate stack trace output. - When catching and logging exceptions without re-raising: always use
logger.exception()(equivalent tologger.error(exc_info=True)) to capture the full stack trace information.
Common Bugs to Avoid
- Pydantic SecretStr defaults: Pydantic models using
SecretStr,SerializableSecretStr, orOptionalSecretStrwithdefault=""creates a bug where the field is initialized asstrinstead of aSecretStrinstance. Instead:- For optional secret fields (e.g.,
OptionalSecretStr): usedefault=None - For non-optional secret fields (e.g.,
SerializableSecretStr): usedefault_factory=lambda: SerializableSecretStr("")to ensure each instance gets a uniqueSecretStrobject
- For optional secret fields (e.g.,
Documentation
- Provide Google-style docstrings for every public module, class, function and CLI command.
- The first line must be a concise description ending with a period (Vale checks this).
- Surround code entities with backticks to avoid Vale false-positives.
- Keep docs in sync with code; the documentation pipeline will fail on Sphinx errors or broken links.
- Documentation quality requirements:
- Documentation must be clear and comprehensive.
- Do not include TODOs, FIXMEs, or placeholder text like "lorem ipsum".
- Avoid offensive or outdated terms.
- Ensure documentation is free of spelling mistakes.
- Do not use words listed in
ci/vale/styles/config/vocabularies/nat/reject.txt. - Words that might appear to be spelling mistakes but are listed in
ci/vale/styles/config/vocabularies/nat/accept.txtare acceptable.
Testing
- Use pytest with
pytest-asynciofor asynchronous code. - Name test files
test_*.pyand store them alongside the code in atests/folder. - Test naming and structure:
- Test functions should be named using the
test_prefix, using snake_case. - Any frequently repeated code should be extracted into pytest fixtures.
- Pytest fixtures should define the name argument when applying the pytest.fixture decorator.
- The fixture function being decorated should be named using the
fixture_prefix or_fixturesuffix, using snake_case. - Example:
@pytest.fixture(name="my_custom_config") def my_custom_config_fixture(): pass
- Test functions should be named using the
- Maintain ≥ 80 % coverage; add or update tests when introducing changes.
- Mock external services with
pytest_httpserverorunittest.mockinstead of hitting live endpoints. - Mark slow tests with
@pytest.mark.slowso they can be skipped in the default test suite. - Mark integration tests which require external services with
@pytest.mark.integrationso they can be skipped in the default test suite, follow the integration testing guidelines in the nat-tests/integration-tests.mdc rules. - Refer to the nat-tests/general.mdc rules for more information on testing.
Security
- Never commit API keys, credentials or personal data; use environment variables or
.envfiles excluded from Git. - Validate and sanitise all user input, especially in web or CLI interfaces.
- Prefer
httpxwith SSL verification enabled by default and follow OWASP Top-10 recommendations. - Periodically run
uv pip list --outdatedand upgrade dependencies.
Continuous Integration
- Never commit code that fails
pre-commit run --all-filesorci/scripts/run_ci_local.sh check. - Every file must start with the standard SPDX Apache-2.0 header.
- Copyright requirements: Confirm that copyright years are up-to-date whenever a file is changed.
- New dependencies must be added to both
pyproject.toml(alphabetically) anduv.lockviauv pip install <pkg> --sync. - Sign commits with
--signoffto comply with the Developer Certificate of Origin (DCO).
Versioning
- The project follows semantic versioning (MAJOR.MINOR.PATCH). Patch releases must remain backward-compatible.
- Version numbers are derived automatically by
setuptools-scm; never hard-code them in code or docs. - Add user-visible changes to
CHANGELOG.mdunder the appropriate section.
Performance
- Use
async/awaitfor I/O-bound work (HTTP, DB, file reads). - Profile CPU-heavy paths with
cProfileormprofbefore optimising. - Cache expensive computations with
functools.lru_cacheor an external cache when appropriate. - Leverage NumPy vectorised operations whenever beneficial and feasible.
Licensing
- All source files must include the SPDX Apache-2.0 header template (copy from an existing file).
- Binary assets committed via Git-LFS must have licensing info recorded in
LICENSE-3rd-party.txtwhen required. - CI verifies headers via
ci/scripts/github/checks.sh; do not bypass this check.