Borrowing it
Nothing to install: this file belongs to ferro-labs/ai-gateway. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/ferro-labs/ai-gateway/main/AGENTS.mdgit clone --depth 1 https://github.com/ferro-labs/ai-gatewayWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/instructions/ferro-labs/ai-gateway/agents-md)<a href="https://agentmods.dev/instructions/ferro-labs/ai-gateway/agents-md"><img src="https://agentmods.dev/badge/instructions/ferro-labs/ai-gateway/agents-md/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/instructions/ferro-labs/ai-gateway/agents-md"><img src="https://agentmods.dev/badge/instructions/ferro-labs/ai-gateway/agents-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.21998 | $0.21998 |
| Opus 5.5 | $0.08799 | $0.08799 |
| Sonnet 5.5 | $0.04400 | $0.04400 |
| Haiku 4.5 | $0.02200 | $0.02200 |
Grade A, and why
ai-gateway AGENTS.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 9d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 1,328 lines — stays where its author put it; the contents beside it link to each section on GitHub.
AGENTS.md
Project Overview
Ferro Labs AI Gateway is a high-performance, open-source AI gateway written in Go. It acts as a unified routing layer between applications and 30 LLM providers (OpenAI, Anthropic, Gemini, Mistral, etc.), offering smart routing, plugin middleware, and API key management — all with an OpenAI-compatible API and transparent pass-through proxy.
- Module:
github.com/ferro-labs/ai-gateway - Go version: 1.26.10+
- License: Apache 2.0
Current Development Snapshot
- 30 provider subpackages — each provider lives in
providers/<id>/<id>.gowith its own test file, one perProviderEntryinproviders/providers_list.go. (providers/core/andproviders/capabilities/are shared code, not providers.) No root-level constructor shims remain. - Unified factory —
providers/factory.goholds types/constants;providers/providers_list.goholds all built-inProviderEntryrecords. Auto-registration viaAllProviders()meansmain.gonever needs editing for new providers. providers/core/split — interfaces incontracts.go; shared types split intochat.go,stream.go,embedding.go,image.go,model.go,constants.go,errors.go.- Single source of truth for name constants —
providers/names.gore-exportsNameXxxfrom each subpackage'sconst Name. - Model discovery —
providers/coreexposesDiscoverOpenAICompatibleModels/DiscoverModelsWithHeadersfor live/modelsenumeration, shared by many OpenAI-compatible providers (fireworks, xai, moonshot, nvidia-nim, novita, …). - Provider coverage — OpenAI, Anthropic, Gemini, Groq, Bedrock, Vertex AI, Hugging Face, Cerebras, Cloudflare, Databricks, DeepInfra, Moonshot, Novita, NVIDIA NIM, OpenRouter, Qwen, SambaNova, and more.
- Built-in OSS plugins — word filter, regex guard, PII redaction, secret scanning, prompt-injection shield, response schema validation, max token, response cache, request logger, rate limit, budget.
- Admin API — dashboard, key management, usage stats, request logs, config history/rollback (
internal/admin/handlers/). - Metrics — Prometheus metrics exposed at
/metrics(pkg/metrics/). - Circuit breaker — per-provider circuit breaker in
pkg/circuitbreaker/. - Observability (v1.1.0) — OpenTelemetry tracing. Public
observability/package (stableProvider/Span/Exporter/Eventseam +gen_ai.*/ferro.*attribute constants);internal/otel/wires the OTLP exporter, W3C propagation, and a customIDGeneratorthat unifies the OTeltrace_idwith the logging trace ID /X-Request-ID;internal/redact/redacts error messages. Defaults to a zero-allocation NoOp when no OTLP endpoint and no exporter are configured. - Capability matrix (v1.2.0) —
providers/capabilities/matrix.gois the single source of truth for which OpenAI chat parameters each provider can express. Providers no longer keep private supported-parameter lists;core.EnforceUnsupportedParamsreads the matrix and appliescompatibility.on_unsupported_param(warn | drop | reject). Served byGET /v1/capabilities. - Conformance suite (v1.2.0) —
test/conformance/builds every provider through itsProviderEntry, points it at an httptest stub returning that provider's native payload, and asserts the translatedcore.Response. No build tag, no network: it runs withmake test.TestConformanceCoveragefails on any provider with neither a fixture nor an allowlist reason. - Plugin failure policy (v1.2.0) — a plugin that denies (
Context.Reject) and a plugin that breaks (error/panic) are distinct:RejectionErrorkeeps its 4xx/429,FailureErroris a 500. Logging and metrics plugins fail open; guardrail, auth, ratelimit, transform, and unknown types fail closed.Rejectis honoured for every type. The type that decides this is the one the plugin reports fromType(), notplugins[].typein config. - Env references (v1.2.0) —
internal/envrefresolves${VAR}at component construction, never at config load, so theConfignever carries a materialised secret into the config-history store,GET /admin/config, or a rollback. A bare$is data ($100,pa$$w0rdsurvive); an undefined variable is an error. - Per-target concurrency (v1.2.0) —
targets[].concurrencybounds in-flight requests per provider with a queue; overflow returnsErrProviderSaturated→ 429. The limiter decorates the provider at the call site (innermost, circuit breaker outermost) and never forges capability interfaces. - Health split (v1.2.0) —
/livez(process alive) and/readyz(ready to serve) replace the single/healthsemantics;/healthis retained. - Plugin short-circuiting (Unreleased) —
Context.Skipis removed; code that sets or reads it no longer compiles.Context.SkipProviderreplaces it and skips the provider call only: every remainingbefore_requestplugin and the wholeafter_requeststage still run, so a response-cache hit can no longer disable a guardrail, rate limiter or budget behind it. Only a rejection or a plugin failure ends thebefore_requeststage, and it ends that stage alone —on_errorstill runs, so a request denied by policy is still recorded.SkipProviderstays set throughafter_requestas a fact (cache-served vs provider-served) that cost recording keys off. - Request attribution (Unreleased) —
Context.Targetnames the routing target a request used: the virtual key that served it, or on a failure the last one attempted, empty when none was attempted (denied by a plugin, no target serves the model, or served from cache). It exists because a failure has no response to read a provider from, which lefton_errorrows naming no provider. Request-log rows also carryapi_key_id— the credential's opaque id, never the credential — so usage is attributable, including a request served from cache, which reaches no provider but is still consumed by a credential. (A cached response is only ever served back to the credential that primed it — the response cache keys onapi_key_id— so a row's credential is the one that made the call, not the one that filled the cache.) A cache-served request is priced at a known zero rather than as though the provider had been called. - Unified request pipeline (Unreleased) — chat, streaming, embeddings and image generation all route through
routeTargetsingateway_pipeline.go. Retry, circuit breaker, per-target concurrency, error classification, metrics and request logging live there once, so the four surfaces cannot drift.targets[].retryis honoured under every routing mode, not onlyfallback. - One completion ceiling (Unreleased) —
max_tokensandmax_completion_tokensare resolved to a single value at every entry point,max_completion_tokenswinning when both are present, so a guardrail and the provider read the same number. See Completion length. - Declared models (Unreleased) —
targets[].modelslets an operator name the models a target serves, joined into the routing index alongside the catalog and live discovery and advertised by/v1/models. It is provider-agnostic and additive: it needs no/modelsendpoint, works offline, and never narrows what a target already serves. See Declared models. - Strategy validation at load (Unreleased) — every strategy is validated by
config.ValidateConfig, so an invalid one is aferrogw validate/ startup error rather than a request-time 500. Unknownconditions[].keyandcontent_conditions[].typevalues are load errors;weight: 0means zero traffic, a negative weight is an error, and an all-zero weight set is an error. - Request identity (Unreleased) —
observability.RequestIdentity(end-user id, session id, request metadata) is set on the request context byinternal/otel.MiddlewarefromX-User-ID,X-Session-IDand the W3Cbaggageentriesuser.id/session.id, or by an embedder throughobservability.ContextWithRequestIdentity; the gateway overlays the OpenAI bodyuser. It is recorded asenduser.id/session.id/ferro.request.metadata.<key>on the request span, onRequestAttrs,EventandRoutingAttempt, and asuser_id/session_idon request-log rows.observability.tracing.attempt_spansopens onegateway.routing.attemptCLIENT span per routing attempt through the optionalobservability.AttemptSpanProvider;observability.tracing.propagate_passthrough(default true) injectstraceparenton/v1/*pass-through forwards and on the fixed-target forwards (/v1/responsescreate and its id sub-routes,/v1/files,/v1/batches). Nothing is inferred and no identity is a body field other thanuser.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 9d ago Changed 810f67a01be4
- 19d ago Changed · +2 tokens per session 60b706f422f6
- 1mo ago Changed · +2 lines · +138 tokens per session 99dacf325f5d
- 1mo ago Changed · +18 lines · +214 tokens per session 2e8d686d3cb4
- 1mo ago Changed · +2 tokens per session ec2a9ead2077
- 2mo ago Changed · +3 lines · +332 tokens per session 3cb0cedef713
- 2mo ago Changed · +64 lines · +1,068 tokens per session dc7456692455
- 2mo ago First seen · 1,241 lines · 20,242 tokens per session scan A 60ba0f2c5cf8
ai-gateway AGENTS.md is an instructions file published in the GitHub repository ferro-labs/ai-gateway (277 stars, last pushed 4d ago), licensed Apache-2.0. It adds 21,998 tokens to every session, about $0.0880 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
ai-gateway AGENTS.md compared with instructions from other repositories
| Mod | Type | Stars | Last push | Licence | Scan | Tokens | Works with |
|---|---|---|---|---|---|---|---|
| ai-gateway AGENTS.mdferro-labs/ai-gateway | Instructions file | 277 | 4d ago | Apache-2.0 | A | 21,998 | Codex, OpenCode |
| vscode buildNext.instructions.mdmicrosoft/vscode | Instructions file | 195k | yesterday | MIT | A | 9,719 | GitHub Copilot |
| next.js AGENTS.mdvercel/next.js | Instructions file | 143k | today | MIT | A | 7,461 | Codex, OpenCode |
| langchain AGENTS.mdlangchain-ai/langchain | Instructions file | 149k | yesterday | MIT | A | 4,680 | Codex, OpenCode |
| vscode oss-third-party-notices.instructions.mdmicrosoft/vscode | Instructions file | 195k | yesterday | MIT | A | 5,516 | GitHub Copilot |
| vscode copilot-instructions.mdmicrosoft/vscode | Instructions file | 195k | yesterday | MIT | A | 3,093 | GitHub Copilot |
| deepseek-harness AGENTS.mddeepseek-ai/deepseek-harness | Instructions file | 274k | 2d ago | MIT | A | 4,313 | Codex, OpenCode |