DO NOT BE OBSEQUIOUS
NEVER use TEST_MODEL_NAME or "test" embedding model outside of test files
Never run git commands that make any changes. (git status and git diff are fine)
NEVER COMMIT CODE. Do not run git commit or any other git commands
that make changes to the repository. Not even git add
When moving, copying or deleting files, use the git commands: git mv, git cp, git rm
- Don't use '!' on the command line, it's some bash magic (even inside single quotes)
- Activate
.venv:make venv; source .venv/bin/activate(run this only once) - To get API keys in ad-hoc code, call
load_dotenv() - Use
pytest testto run tests in test/ - Use
pyrightto check type annotations in src/, tools/, tests/, examples/ - Ignore build/, dist/
- You can also use the pylance extension for type checking in VS Code
- Use
make checkto type-check all files - Use
make testto run all tests - Use
make check testto runmake checkand if it passes also runmake test - Use
make formatto format all files usingblack. Do this before reporting success.
- Use
uv add <package>to add new dependencies - Use
uv add <package> --upgradeto upgrade existing packages - Important: uv automatically updates
pyproject.tomlwhen adding/upgrading packages - Do NOT manually edit
pyproject.tomldependency versions after running uv commands - uv maintains consistency between
pyproject.toml,uv.lock, and installed packages - Trust uv's automatic version resolution and file management
IMPORTANT! YOU ARE NOT DONE UNTIL make check test format PASSES
When generating Python code (e.g. when translating TypeScript to Python), please follow these guidelines:
- When creating a new file, add a copyright header to the top:
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
-
Assume Python 3.12
-
Always strip trailing spaces
-
Keep class and type names in
PascalCase -
Use
python_casefor variable/field and function/method names -
Use
Literalfor unions of string literals -
Keep union notation (
X | Y) for other unions -
Use
Protocolfor interfaces whose name starts withIfollowed by a capital letter -
Use
dataclassfor other classes and structured types -
Use
typefor type aliases (PascalCaseagain) -
Use
list,tuple,dict,setetc., notListetc. -
Translate
foo?: stringtofoo: str | None = None -
When writing tests:
- don't mock; use the regular implementation (maybe introduce a fixture to create it)
- assume
pytest; useassertstatements - match the type annotations of the tested functions
- read the code of the tested functions to understand their behavior
- When using fixtures:
- Fully type-annotate the fixture definitions (including return type)
- Fully type-annotate fixture usages
-
Don't put imports inside functions. Put them at the top of the file with the other imports. Exception: imports in a
if __name__ == "__main__":block or amain()function. Another exception: pydantic and logfire. Final exception: to avoid circular import errors. -
Import Architecture Rules:
- Never import a symbol from a module that just re-exports it
- Always import directly from the module that defines the symbol
- Exception: Package
__init__.pyfiles that explicitly re-export with__all__ - Exception: Explicit re-export patterns like
from ... import X as Xor marked with "# For export" - This prevents circular imports and makes dependencies clear
-
Order imports alphabetically after lowercasing; group them as follows (with a blank line between groups):
- standard library imports
- established third-party libraries
- experimental third-party libraries (e.g.
typechat) - local imports (e.g.
from typeagent.knowpro import ...)
-
Error Handling: Don't use
try/except Exceptionto catch errors broadly. Let errors bubble up naturally for proper error handling and debugging at higher levels. -
Code Validation: Don't use
py_compilefor syntax checking. Usepyrightormake checkinstead for proper type checking and validation. -
Deprecations: Don't deprecate things -- just delete them and fix the usage sites. Don't create backward compatibility APIs or exports or whatever. Fix the usage sites.