lm-proxy
AGENTS.md154 starsChanged 3 months agoMITView on GitHub
LM-Proxy is a lightweight, OpenAI-compatible HTTP proxy/gateway (FastAPI + MicroCore) that unifies access to multiple LLM providers (OpenAI, Anthropic, Google, local PyTorch inference) behind a single OpenAI-format API. It runs as a standalone server or as an importable Python library. Run a single test: pytest tests/test_core.py::test_name -v pytest config lives in pyproject.toml: asyncio_mode = "auto" (async tests need no decorator), testpaths = ["tests"]. Optional provider deps are extras: pip install -e .[anthropic,google] or .[all]; .[test] for the test toolchain. The…
- Reads credentials
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repositoryOne other file it gives its agents.
- CLAUDE.mdCLAUDE.md
The file
We split this AGENTS.md into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 21
Run a single test: pytest tests/test_core.py::test_name -v
- Very specific: line 61
Never attribute work to an AI tool: no assistant/model/vendor names or "AI-generated" markers in branch names, commit messages, PR text, …
- Distinctive: line 62
Keep it simple (KISS). Be laconic: minimal code, minimal docs, minimal PR/commit text.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
What this is
LM-Proxy is a lightweight, OpenAI-compatible HTTP proxy/gateway (FastAPI + MicroCore) that unifies access to multiple LLM providers (OpenAI, Anthropic, Google, local PyTorch inference) behind a single OpenAI-format API. It runs as a standalone server or as an importable Python library.
Commands
make install # pip install -e .
make run # fastapi run lm_proxy (or: python -m lm_proxy / lm-proxy)
make test # pytest --log-cli-level=INFO
make integration-test # pytest tests/test_integration.py -v
make cs # flake8 . (lint)
make black # black . (format; line-length 100)
make build # python multi-build.py (build dist packages)Run a single test: pytest tests/test_core.py::test_name -v
pytest config lives in pyproject.toml: asyncio_mode = "auto" (async tests need no decorator), testpaths = ["tests"].
Optional provider deps are extras: pip install -e .[anthropic,google] or .[all]; .[test] for the test toolchain.
The server loads config.toml from the cwd by default (lm-proxy --config <path> to override; --env to pick a .env file). The repo-root config.toml is the dev/reference config; more samples live in examples/.
Architecture
Request flow for POST /v1/chat/completions (lm_proxy/core.py:chat_completions):
fail_if_service_disabled()→check()validates the virtual/client API key viaconfig.api_key_check, returning a group name (and optionaluser_info).resolve_connection_and_model()matches the requested model againstconfig.routingpatterns (fnmatch wildcards). Rule values are"connection.model"or"connection.*"(*passes the requested model name through unchanged).- Group
allowed_connectionsis enforced (comma-separated connection names or"*"; groups also hold theapi_keyslist checked by the default validator). beforehandlers (middleware) run sequentially, each receiving aRequestContext.- The resolved connection — a MicroCore
llm_async_function— is invoked. Streaming requests go throughprocess_stream()(SSEtext/event-stream); non-streaming return a JSONchoicesarray. log_non_blocking()fires all configured loggers as async tasks.
GET /v1/models (models_endpoint.py) lists config.routing keys filtered by the caller group's allowed connections; model_listing_mode controls wildcard-pattern handling and model_info merges extra metadata per model.
Key modules:
app.py— Typer CLI (cli_app) + FastAPI factory (web_app). Endpoints registered underconfig.api_prefix(default/v1).bootstrap.py—bootstrap()loads.env, sets up logging/debug, thenEnv.init()builds theenvruntime singleton: resolves connections (into MicroCore async LLM functions), components, loggers, andbeforehandlers. Most runtime code reads globalenv.config,env.connections, etc.config.py— PydanticConfigmodel (extra="forbid").Config.load()dispatches by file extension to a loader registered as aconfig.loadersentry point (seepyproject.toml), supporting TOML / YAML / JSON / Python configs. Env-var refs (env:VAR_NAME) are expanded viareplace_env_strings_recursive.base_types.py—ChatCompletionRequest(the OpenAI-shaped request) andRequestContext(the per-request object threaded through handlers and loggers).utils.py:resolve_instance_or_callable— the central extensibility primitive: turns a config value (dotted string"my.module.fn", dict withclass/functionkey + kwargs, or callable) into a live object. Used for connections, api_key_check, handlers, loggers, components.
Extension points (all configured by reference, no core changes needed):
- Connections (
[connections]) — a MicroCore config dict (api_type, keys) OR a custom async callable. Seestrategies/fallback.pyfor an example custom connection. - api_key_check —
api_key_check/hascheck_api_key_in_config(default),CheckAPIKeyWithRequest(external HTTP/OIDC validation), andallow_all. A validator returns a group name (or(group, user_info)tuple), or falsy to reject. - Handlers / middleware (
[[before]]) —handlers/shipsRateLimiterandHTTPHeadersForwarder. Any callable taking aRequestContext. - Loggers (
[[loggers]]) —loggers.py(BaseLogger,JsonLogWriter,LogEntryTransformer). Run non-blocking.
Conventions
- Errors surfaced to clients use OpenAI's error envelope (
{"error": {"message","type","param","code"}}); seeerrors.py:OpenAIHTTPException. - Debug mode (
LM_PROXY_DEBUGenv or--debug) raises full tracebacks and sets DEBUG logging; otherwise exceptions are logged and a sanitized error returned. CLI flags override env. - Streaming errors are not HTTP errors: they arrive as a final SSE chunk carrying an
errorobject andfinish_reason: "error", followed bydata: [DONE]. config.encryption_keysalts the MD5api_key_idhash used to identify keys in logs — client API keys are never logged raw.- Supported Python: 3.11–3.13.
- Never attribute work to an AI tool: no assistant/model/vendor names or "AI-generated" markers in branch names, commit messages, PR text, comments, or docs.
- Keep it simple (KISS). Be laconic: minimal code, minimal docs, minimal PR/commit text.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

