Catalog

Package: agentrouter.catalog.v1 Service: CatalogService

Endpoints

List providers

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

What it does: Returns all registered AI providers. Supports cursor-based pagination via page_size and page_token.

Request fields:

FieldRequiredDescription
pagenoPage size and continuation token for cursor-based pagination.
include_disablednoReturn disabled providers alongside enabled ones. Defaults false, which is the enabled-only view every interactive caller expects. A catalogue sync must set it: without the full picture it cannot tell a disabled provider from an absent one, so it would re-propose every disabled row as new on each run.

Response fields:

FieldRequiredDescription
providersnoProviders on this page, in catalog order.
pagenoPagination cursor; carries next_page_token for the following call.
{"signatures":{"go":"func (x *CatalogClient) ListProviders(ctx context.Context, req *catalogv1.ListProvidersRequest) (*catalogv1.ListProvidersResponse, error)","python":"list_providers(req: catalog_pb2.ListProvidersRequest) -\u003e ListProvidersResponse","typescript":"listProviders(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.ListProvidersRequestSchema\u003e): Promise\u003cListProvidersResponse\u003e","cli":"tare api catalog providers","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.ListProvidersRequest{}\n\n\tresp, err := client.Catalog().ListProviders(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/listproviders\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.ListProvidersRequest()\ntry:\n    result = client.catalog.list_providers(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.listProviders(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog providers","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/catalog/providers","slug":"list-providers"}

Get a provider

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

What it does: Returns a single provider by id.

Request fields:

FieldRequiredDescription
idyesProvider id to fetch. prov_<ulid>.

Response fields:

FieldRequiredDescription
providernoThe requested provider.
{"signatures":{"go":"func (x *CatalogClient) GetProvider(ctx context.Context, req *catalogv1.GetProviderRequest) (*catalogv1.GetProviderResponse, error)","python":"get_provider(req: catalog_pb2.GetProviderRequest) -\u003e GetProviderResponse","typescript":"getProvider(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.GetProviderRequestSchema\u003e): Promise\u003cGetProviderResponse\u003e","cli":"tare api catalog provider \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.GetProviderRequest{}\n\n\tresp, err := client.Catalog().GetProvider(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/getprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.GetProviderRequest()\ntry:\n    result = client.catalog.get_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.getProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog provider \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/catalog/providers/{id}","slug":"get-a-provider"}

List models

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

What it does: Returns catalog models, optionally filtered to a single provider via the provider_id query parameter.

Request fields:

FieldRequiredDescription
provider_idnoFilter to models belonging to this provider. Empty returns all models.
pagenoPage size and continuation token for cursor-based pagination.
include_disablednoReturn disabled models alongside enabled ones. Defaults false. See ListProvidersRequest.include_disabled for why a sync requires it.

Response fields:

FieldRequiredDescription
modelsnoModels on this page, in catalog order.
pagenoPagination cursor; carries next_page_token for the following call.
{"signatures":{"go":"func (x *CatalogClient) ListModels(ctx context.Context, req *catalogv1.ListModelsRequest) (*catalogv1.ListModelsResponse, error)","python":"list_models(req: catalog_pb2.ListModelsRequest) -\u003e ListModelsResponse","typescript":"listModels(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.ListModelsRequestSchema\u003e): Promise\u003cListModelsResponse\u003e","cli":"tare api catalog models","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.ListModelsRequest{}\n\n\tresp, err := client.Catalog().ListModels(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/listmodels\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.ListModelsRequest()\ntry:\n    result = client.catalog.list_models(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.listModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog models","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/catalog/models","slug":"list-models"}

Get a model

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

What it does: Returns a single model by id (UUID) or by unique model name, including its pricing, context window, capabilities, modalities, and limits.

Request fields:

FieldRequiredDescription
idyesModel id (UUID) or unique model name. A UUID is looked up by id; any other value is resolved by model name across the visible catalog. A name that matches models from multiple providers is rejected with InvalidArgument naming the candidates.

Response fields:

FieldRequiredDescription
modelnoThe requested model.
{"signatures":{"go":"func (x *CatalogClient) GetModel(ctx context.Context, req *catalogv1.GetModelRequest) (*catalogv1.GetModelResponse, error)","python":"get_model(req: catalog_pb2.GetModelRequest) -\u003e GetModelResponse","typescript":"getModel(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.GetModelRequestSchema\u003e): Promise\u003cGetModelResponse\u003e","cli":"tare api catalog model \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.GetModelRequest{}\n\n\tresp, err := client.Catalog().GetModel(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/getmodel\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.GetModelRequest()\ntry:\n    result = client.catalog.get_model(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.getModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog model \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/catalog/models/{id}","slug":"get-a-model"}

Create or update a provider

Changed in v0.5.0 (new features): Catalog audit entries now say whether a write came from a batch. A sync run's several hundred UPSERT rows carry batched: true in their metadata and interactive edits carry batched: false, so the audit view can be filtered to just the changes a person made.

Changed in v0.2.0 (behaviour changes): Creating a provider through the catalog API no longer enables it. A provider created without is_enabled now arrives disabled, and registering a model under it is refused until it is enabled: enabling a provider is what makes the data plane start fetching its credentials, so one created before it has a credential cannot serve. Existing providers are unaffected.

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

Changed in v0.2.0 (bug fixes): Editing a model or provider through the catalog API no longer switches it back on. Every write used to assert "enabled" whether or not it mentioned enablement, so an administrator's deliberate disable was reverted by the next unrelated edit (a price correction or a rename was enough) with nothing recording it. Enablement now changes only when a request actually asks it to. One consequence: a provider created through the API now arrives disabled, because enabling a provider is what makes the data plane start fetching its credentials, and one created before it has a credential cannot serve. Existing providers are unaffected, and enabling a new one is a single further call. If you script provider creation and relied on it being immediately enabled, ask for it explicitly.

Changed in v0.1.5 (bug fixes): Editing a provider's connection settings through the catalog API (base URL or credential, or removing the provider) now takes effect on projects that route on their own hostname (strict isolation). Previously only the shared route map picked up the change, so a project with its own hostname kept serving the old provider configuration until an unrelated change happened to refresh it.

What it does: Creates or fully replaces a provider record. is_enabled is tri-state: omit it and the stored value is left alone (a provider an operator disabled stays disabled). A new provider defaults to disabled -- the data plane does not reconcile an AIServiceBackend or fetch credentials for it until it is both enabled and credentialed via SetProviderCredential.

Request fields:

FieldRequiredDescription
idyesProvider slug, e.g. "openai". Natural key; required. Must be canonical lowercase alphanumeric [a-z0-9]+ (no hyphens, spaces, or uppercase).
display_nameyesHuman-readable display name, e.g. "OpenAI".
base_urlyesProvider API base URL. The CLI flag is renamed to --provider-base-url to avoid colliding with the root command's persistent --base-url (which overrides the active profile's API URL for one invocation).
supported_auth_schemesnoAuth schemes this provider supports, e.g. ["bearer"].
metadatanoNon-secret data-path semantics stored on ai_providers.metadata: type (client request shape), backend_schema (backend translator), api_key_flavor (key injection behavior), and operation_variants (per-operation provider variants). Merged over any existing metadata rather than replacing it, so supported_auth_schemes and credential_suffix survive. Message-typed, so protoc-gen-ia-cli skips it -- this field is for catalog sync, not interactive CLI use.
is_enablednoEnable or disable the provider. UNSET LEAVES THE STORED VALUE UNTOUCHED, and that is the default: a catalog sync must not revert an operator's deliberate disable, and a provider must not become enabled (and so reconciled by the data plane) before it has a credential. On insert, unset means false.
suppress_route_regennoSkip the synchronous default GLOBAL_ROUTES regeneration this write would otherwise trigger. For batch callers only: a bulk sync that regenerates per record blocks on one configurator round-trip each time. A caller that sets this MUST fire configurator.TriggerUpdate once when the batch completes, or the data plane keeps serving the previous route map until the next periodic sync.

Response fields:

FieldRequiredDescription
idoutput-onlyResource name prov_<ulid>. Server-assigned; immutable.
nameyesMachine-readable slug, e.g. "openai", "anthropic", "awsbedrock". Unique. Canonical form is lowercase alphanumeric [a-z0-9]+ (no hyphens, spaces, or uppercase) -- it is matched hyphen-insensitively at inference time, so UpsertProvider requires this canonical form on write.
display_nameyesHuman-readable display name, e.g. "OpenAI".
base_urlyesBase URL for all models served by this provider, e.g. "https://api.openai.com".
supported_auth_schemesnoAuth schemes this provider supports, e.g. "bearer", "aws-sigv4-static".
credential_suffixoutput-onlyLast 4 chars of the stored platform credential (e.g. "sk-..**4a2f"). Empty if no platform credential has been set. BYOK keys are tracked separately via aikeys.v1.
metadatanoNon-secret data-path semantics from ai_providers.metadata: type, backend_schema, api_key_flavor, operation_variants. The credential keys are never included.
is_enablednoWhether this provider is enabled. A disabled provider is absent from the data plane's route map and its credentials are not reconciled. Only visible when the request set include_disabled -- the default list returns enabled providers only, so this always reads true there.
created_atoutput-onlyWhen this provider record was created.
updated_atoutput-onlyWhen this provider record was last modified.
{"signatures":{"go":"func (x *CatalogClient) UpsertProvider(ctx context.Context, req *catalogv1.UpsertProviderRequest) (*catalogv1.Provider, error)","python":"upsert_provider(req: catalog_pb2.UpsertProviderRequest) -\u003e Provider","typescript":"upsertProvider(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.UpsertProviderRequestSchema\u003e): Promise\u003cProvider\u003e","cli":"tare api catalog providers upsert --id $ID --display-name $DISPLAY_NAME --base-url $BASE_URL","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"id\": \"...\",\n    \"display_name\": \"...\",\n    \"base_url\": \"...\",\n    \"supported_auth_schemes\": [],\n    \"metadata\": {},\n    \"is_enabled\": false,\n    \"suppress_route_regen\": false\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.UpsertProviderRequest{}\n\n\tresp, err := client.Catalog().UpsertProvider(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/upsertprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.UpsertProviderRequest()\ntry:\n    result = client.catalog.upsert_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.upsertProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog providers upsert --id $ID --display-name $DISPLAY_NAME --base-url $BASE_URL","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"id\": \"...\",\n    \"display_name\": \"...\",\n    \"base_url\": \"...\",\n    \"supported_auth_schemes\": [],\n    \"metadata\": {},\n    \"is_enabled\": false,\n    \"suppress_route_regen\": false\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/catalog/providers","slug":"create-or-update-a-provider"}

Create or update a model

Changed in v0.5.0 (new features): Catalog audit entries now say whether a write came from a batch. A sync run's several hundred UPSERT rows carry batched: true in their metadata and interactive edits carry batched: false, so the audit view can be filtered to just the changes a person made.

Changed in v0.2.0 (new features): The catalog API now carries a model's whole record. Modalities, rate and size limits, per-model backend URLs, non-per-token pricing, the cache-write rate, and free-form metadata (including the display name and the deprecation and retirement dates) can now be written and read back, where before they could only be set by editing the database. Providers likewise carry their routing metadata (upstream type, backend schema, API-key flavor and per-operation variants), which had no representation at all. Listing providers or models also accepts include_disabled, so the full catalog can be read rather than only the enabled part.

Changed in v0.2.0 (bug fixes): Editing a model or provider through the catalog API no longer switches it back on. Every write used to assert "enabled" whether or not it mentioned enablement, so an administrator's deliberate disable was reverted by the next unrelated edit (a price correction or a rename was enough) with nothing recording it. Enablement now changes only when a request actually asks it to. One consequence: a provider created through the API now arrives disabled, because enabling a provider is what makes the data plane start fetching its credentials, and one created before it has a credential cannot serve. Existing providers are unaffected, and enabling a new one is a single further call. If you script provider creation and relied on it being immediately enabled, ask for it explicitly.

Changed in v0.2.0 (bug fixes): A partial edit through the catalog API no longer blanks the fields it did not mention. Changing one property of a model (its mode, say) cleared its capabilities, per-token prices and context window, because an omitted value was written over the stored one rather than skipped. Fields a request does not carry are now left as they are. The model's modalities, limits, backend URLs and pricing extras follow the same rule now that the API can carry them at all; they were never reachable before, so nothing was lost through them.

Changed in v0.1.5 (bug fixes): Editing or removing a model through the catalog API (its upstream name, capabilities, or pricing) now takes effect on projects that route on their own hostname (strict isolation). Previously only the shared route map picked up the change, so a project with its own hostname kept serving the old model configuration until an unrelated change happened to refresh it. Companion to the provider-config fix above.

What it does: Creates or fully replaces a model record. The provider must already exist (FAILED_PRECONDITION otherwise), and must be enabled if this model is going to be enabled -- an enabled model under a disabled provider could never become routable, yet would read as available. Writing an explicitly DISABLED model under a disabled provider is allowed: neither appears in any route map, so nothing is misrepresented, and it is how a catalog sync stages a provider's models before an operator turns the provider on. A successful write propagates to the gateway automatically (no separate publish step): the model appears in the data plane's /v1/models and becomes promptable once the refreshed configuration lands. Poll /v1/models to confirm. The exception is suppress_route_regen, which defers that propagation to the caller's own configurator.TriggerUpdate. is_enabled is tri-state: omit it and the stored value is left alone, so a model an operator disabled is not silently re-enabled by a later write. A new model defaults to enabled.

Request fields:

FieldRequiredDescription
provider_idyesProvider slug this model belongs to.
nameyesLogical model name, e.g. "gpt-4o". Unique within provider.
upstream_modelnoProvider-side model id (defaults to name when empty).
input_per_millionnoCost in USD per million input tokens (decimal string).
output_per_millionnoCost in USD per million output tokens (decimal string).
cache_read_per_millionnoCost in USD per million cache-read tokens. Empty if not applicable.
max_cost_per_requestnoHard cap in USD per single request. Empty means no cap.
max_context_tokensnoMaximum context window in tokens.
capabilitiesnoCapabilities this model supports, e.g. ["chat", "embeddings"].
modenoModel mode. One of: chat, completion, embedding, image_generation, moderation, rerank, responses, audio_speech, audio_transcription. Defaults to "chat" when empty. Required downstream: the data plane route map cannot be built for a model with an unset mode.
caching_per_millionnoCost in USD per million cache-WRITE tokens (ai_models.caching_tokens_price_per_million). Distinct from cache_read_per_million above. Empty if not applicable.
input_modalitiesnoInput modalities the model accepts, e.g. ["text", "image"]. Persisted as ai_models.modalities->'input'. Scalar so the CLI can flag it.
output_modalitiesnoOutput modalities the model produces, e.g. ["text"]. Persisted as ai_models.modalities->'output'.
backend_urlsnoPer-model backend URL overrides (ai_models.backend_urls). Empty leaves the model served from its provider's base_url.
limitsnoRate and size caps (ai_models.limits). Open-ended by design -- rpm, tpm, max_output_tokens, max_images_per_prompt and ~10 more. A Struct rather than the Limits message on the read path, which models only rpm/tpm and so cannot round-trip a real catalog entry.
additional_price_per_millionnoNon-per-token pricing (ai_models.additional_price_per_million): per-image, per-second, per-character, batch and cache-creation rates.
metadatanoFree-form model metadata (ai_models.metadata), merged over any existing value rather than replacing it. Carries the lifecycle and presentation fields the catalog depends on: display_name, deprecated, deprecated_date, retirement_date, release_date, aliases, source_url. The server always writes upstream_model and max_cost_per_request into this same jsonb, so keys set here must not collide with those two.
is_enablednoEnable or disable the model. UNSET LEAVES THE STORED VALUE UNTOUCHED, and that is the default -- see UpsertProviderRequest for the reasoning. On insert, unset means true: an explicitly-created model with no opinion stated is routable, which preserves the behavior every existing caller relies on.
suppress_route_regennoSkip the synchronous default GLOBAL_ROUTES regeneration. Batch callers only; see UpsertProviderRequest.suppress_route_regen for the flush obligation this creates.

Response fields:

FieldRequiredDescription
idoutput-onlyResource name mdl_<ulid>. Server-assigned; immutable.
provider_idyesProvider this model belongs to. prov_<ulid>.
nameyesLogical name used in routing and billing, e.g. "gpt-4o". Unique within a provider.
upstream_modelyesProvider-side model id sent as body.model to upstream, e.g. "gpt-4o-2024-11-20".
pricingnoPer-token pricing rates.
max_context_tokensnoMaximum context window in tokens.
capabilitiesnoCapabilities this model supports, e.g. "chat", "embeddings", "images".
modenoModel mode, e.g. "chat", "embedding", "image_generation". Surfaces the persisted value so callers can confirm what UpsertModel stored; reads default it to "chat" when the stored value is unset.
modalitiesnoInput/output modalities from ai_models.modalities.
limitsnoRate limits from ai_models.limits, narrowed to rpm/tpm. Retained for compatibility; prefer limits_json, which carries the column whole.
backend_urlsnoPer-model backend URL overrides (ai_models.backend_urls). Empty means the model is served from its provider's base_url.
additional_price_per_millionnoNon-per-token pricing (ai_models.additional_price_per_million).
metadatanoFull model metadata (ai_models.metadata), including the lifecycle fields a catalogue consumer needs: display_name, deprecated, deprecated_date, retirement_date, release_date, aliases.
limits_jsonnoai_models.limits in full. The limits field above models only rpm and tpm, so it cannot represent a real catalogue entry -- max_output_tokens, max_images_per_prompt, rpd and ~10 more live only here. Read this one when round-tripping.
is_enablednoWhether this model is enabled. A disabled model is absent from the data plane's /v1/models. Only meaningful when the request set include_disabled -- the default list returns enabled models only.
created_atoutput-onlyWhen this model record was created.
updated_atoutput-onlyWhen this model record was last modified.
{"signatures":{"go":"func (x *CatalogClient) UpsertModel(ctx context.Context, req *catalogv1.UpsertModelRequest) (*catalogv1.Model, error)","python":"upsert_model(req: catalog_pb2.UpsertModelRequest) -\u003e Model","typescript":"upsertModel(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.UpsertModelRequestSchema\u003e): Promise\u003cModel\u003e","cli":"tare api catalog models upsert --provider-id $PROVIDER_ID --name $NAME","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_id\": \"...\",\n    \"name\": \"...\",\n    \"upstream_model\": \"...\",\n    \"input_per_million\": \"...\",\n    \"output_per_million\": \"...\",\n    \"cache_read_per_million\": \"...\",\n    \"max_cost_per_request\": \"...\",\n    \"max_context_tokens\": 0,\n    \"capabilities\": [],\n    \"mode\": \"...\",\n    \"caching_per_million\": \"...\",\n    \"input_modalities\": [],\n    \"output_modalities\": [],\n    \"backend_urls\": [],\n    \"limits\": {},\n    \"additional_price_per_million\": {},\n    \"metadata\": {},\n    \"is_enabled\": false,\n    \"suppress_route_regen\": false\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.UpsertModelRequest{}\n\n\tresp, err := client.Catalog().UpsertModel(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/upsertmodel\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.UpsertModelRequest()\ntry:\n    result = client.catalog.upsert_model(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.upsertModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog models upsert --provider-id $PROVIDER_ID --name $NAME","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_id\": \"...\",\n    \"name\": \"...\",\n    \"upstream_model\": \"...\",\n    \"input_per_million\": \"...\",\n    \"output_per_million\": \"...\",\n    \"cache_read_per_million\": \"...\",\n    \"max_cost_per_request\": \"...\",\n    \"max_context_tokens\": 0,\n    \"capabilities\": [],\n    \"mode\": \"...\",\n    \"caching_per_million\": \"...\",\n    \"input_modalities\": [],\n    \"output_modalities\": [],\n    \"backend_urls\": [],\n    \"limits\": {},\n    \"additional_price_per_million\": {},\n    \"metadata\": {},\n    \"is_enabled\": false,\n    \"suppress_route_regen\": false\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/catalog/models","slug":"create-or-update-a-model"}

Set a provider credential

Changed in v0.1.5 (bug fixes): Editing a provider's connection settings through the catalog API (base URL or credential, or removing the provider) now takes effect on projects that route on their own hostname (strict isolation). Previously only the shared route map picked up the change, so a project with its own hostname kept serving the old provider configuration until an unrelated change happened to refresh it.

What it does: Stores or rotates the credential used to authenticate requests to this provider. The plaintext is never returned; the provider's credential_suffix reflects the last 4 characters.

Request fields:

FieldRequiredDescription
idyesProvider id / slug.
credentialyesPlaintext credential (API key, bearer token, etc.). Stored server-side under envelope encryption and never returned. Provider.credential_suffix reflects the last 4 chars.

Response fields:

FieldRequiredDescription
idoutput-onlyResource name prov_<ulid>. Server-assigned; immutable.
nameyesMachine-readable slug, e.g. "openai", "anthropic", "awsbedrock". Unique. Canonical form is lowercase alphanumeric [a-z0-9]+ (no hyphens, spaces, or uppercase) -- it is matched hyphen-insensitively at inference time, so UpsertProvider requires this canonical form on write.
display_nameyesHuman-readable display name, e.g. "OpenAI".
base_urlyesBase URL for all models served by this provider, e.g. "https://api.openai.com".
supported_auth_schemesnoAuth schemes this provider supports, e.g. "bearer", "aws-sigv4-static".
credential_suffixoutput-onlyLast 4 chars of the stored platform credential (e.g. "sk-..**4a2f"). Empty if no platform credential has been set. BYOK keys are tracked separately via aikeys.v1.
metadatanoNon-secret data-path semantics from ai_providers.metadata: type, backend_schema, api_key_flavor, operation_variants. The credential keys are never included.
is_enablednoWhether this provider is enabled. A disabled provider is absent from the data plane's route map and its credentials are not reconciled. Only visible when the request set include_disabled -- the default list returns enabled providers only, so this always reads true there.
created_atoutput-onlyWhen this provider record was created.
updated_atoutput-onlyWhen this provider record was last modified.
{"signatures":{"go":"func (x *CatalogClient) SetProviderCredential(ctx context.Context, req *catalogv1.SetProviderCredentialRequest) (*catalogv1.Provider, error)","python":"set_provider_credential(req: catalog_pb2.SetProviderCredentialRequest) -\u003e Provider","typescript":"setProviderCredential(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.SetProviderCredentialRequestSchema\u003e): Promise\u003cProvider\u003e","cli":"tare api catalog providers set-credential \u003cid\u003e --credential $CREDENTIAL","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H.../credential\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"credential\": \"...\"\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.SetProviderCredentialRequest{}\n\n\tresp, err := client.Catalog().SetProviderCredential(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/setprovidercredential\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.SetProviderCredentialRequest()\ntry:\n    result = client.catalog.set_provider_credential(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.setProviderCredential(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog providers set-credential \u003cid\u003e --credential $CREDENTIAL","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H.../credential\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"credential\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/catalog/providers/{id}/credential","slug":"set-a-provider-credential"}

Delete a provider

Changed in v0.1.5 (bug fixes): Editing a provider's connection settings through the catalog API (base URL or credential, or removing the provider) now takes effect on projects that route on their own hostname (strict isolation). Previously only the shared route map picked up the change, so a project with its own hostname kept serving the old provider configuration until an unrelated change happened to refresh it.

What it does: Removes a provider, along with the project assignments that granted access to it. Refuses while any model still references it, while any BYOK API key is registered against it (revoke those keys first), or when it is the only provider assigned to a project that still has models assigned. On success, any revoked BYOK keys for this provider and their stored secrets are permanently removed, and the provider's own stored credential is retired.

Request fields:

FieldRequiredDescription
idyesId of the provider to delete. prov_<ulid>.
{"signatures":{"go":"func (x *CatalogClient) DeleteProvider(ctx context.Context, req *catalogv1.DeleteProviderRequest) error","python":"delete_provider(req: catalog_pb2.DeleteProviderRequest) -\u003e None","typescript":"deleteProvider(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.DeleteProviderRequestSchema\u003e): Promise\u003cvoid\u003e","cli":"tare api catalog providers delete \u003cid\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.DeleteProviderRequest{}\n\n\tif err := client.Catalog().DeleteProvider(ctx, req); err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Println(\"ok\")\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/deleteprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.DeleteProviderRequest()\ntry:\n    result = client.catalog.delete_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.deleteProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog providers delete \u003cid\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/catalog/providers/{id}","slug":"delete-a-provider"}

Delete a model

Changed in v0.1.5 (bug fixes): Editing or removing a model through the catalog API (its upstream name, capabilities, or pricing) now takes effect on projects that route on their own hostname (strict isolation). Previously only the shared route map picked up the change, so a project with its own hostname kept serving the old model configuration until an unrelated change happened to refresh it. Companion to the provider-config fix above.

What it does: Removes a model entry.

Request fields:

FieldRequiredDescription
idyesId of the model to delete. mdl_<ulid>.
{"signatures":{"go":"func (x *CatalogClient) DeleteModel(ctx context.Context, req *catalogv1.DeleteModelRequest) error","python":"delete_model(req: catalog_pb2.DeleteModelRequest) -\u003e None","typescript":"deleteModel(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.DeleteModelRequestSchema\u003e): Promise\u003cvoid\u003e","cli":"tare api catalog models delete \u003cid\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/catalog/models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.DeleteModelRequest{}\n\n\tif err := client.Catalog().DeleteModel(ctx, req); err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Println(\"ok\")\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/deletemodel\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.DeleteModelRequest()\ntry:\n    result = client.catalog.delete_model(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.deleteModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api catalog models delete \u003cid\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/catalog/models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/catalog/models/{id}","slug":"delete-a-model"}

Assign a model to a project

What it does: Grants a project access to a catalog model. Idempotent: re-assigning a model is a no-op. The model's provider must be enabled (FAILED_PRECONDITION otherwise) -- a model under a disabled provider is absent from the route map and could not be served. Propagates automatically to any Project Gateway attached to the project (per-gateway route maps serve only assigned models); no separate publish step is needed.

Request fields:

FieldRequiredDescription
customer_idnoDefaults to the caller's session customer when empty.
project_idnoDefaults to the caller's session project when empty.
model_idyesCatalog model id (uuid).

Response fields:

FieldRequiredDescription
entrynoThe created (or already-existing) project-to-model assignment.
{"signatures":{"go":"func (x *CatalogClient) AssignModelToProject(ctx context.Context, req *catalogv1.AssignModelToProjectRequest) (*catalogv1.AssignModelToProjectResponse, error)","python":"assign_model_to_project(req: catalog_pb2.AssignModelToProjectRequest) -\u003e AssignModelToProjectResponse","typescript":"assignModelToProject(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.AssignModelToProjectRequestSchema\u003e): Promise\u003cAssignModelToProjectResponse\u003e","cli":"tare api project models add --model-id $MODEL_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model_id\": \"...\"\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.AssignModelToProjectRequest{}\n\n\tresp, err := client.Catalog().AssignModelToProject(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/assignmodeltoproject\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.AssignModelToProjectRequest()\ntry:\n    result = client.catalog.assign_model_to_project(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.assignModelToProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api project models add --model-id $MODEL_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model_id\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/models","slug":"assign-a-model-to-a-project"}

List project models

What it does: Returns every catalog model assigned to a project.

Request fields:

FieldRequiredDescription
customer_idnoDefaults to the caller's session customer when empty.
project_idnoDefaults to the caller's session project when empty.

Response fields:

FieldRequiredDescription
entriesnoEvery model assigned to the project, each joined with its catalog Model.
{"signatures":{"go":"func (x *CatalogClient) ListProjectModels(ctx context.Context, req *catalogv1.ListProjectModelsRequest) (*catalogv1.ListProjectModelsResponse, error)","python":"list_project_models(req: catalog_pb2.ListProjectModelsRequest) -\u003e ListProjectModelsResponse","typescript":"listProjectModels(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.ListProjectModelsRequestSchema\u003e): Promise\u003cListProjectModelsResponse\u003e","cli":"tare api project models list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.ListProjectModelsRequest{}\n\n\tresp, err := client.Catalog().ListProjectModels(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/listprojectmodels\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.ListProjectModelsRequest()\ntry:\n    result = client.catalog.list_project_models(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.listProjectModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api project models list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/models","slug":"list-project-models"}

Unassign a model from a project

What it does: Removes a project's access to a catalog model.

Request fields:

FieldRequiredDescription
customer_idnoDefaults to the caller's session customer when empty.
project_idnoDefaults to the caller's session project when empty.
model_idyesCatalog model id (uuid) to unassign from the project.

Response fields:

FieldRequiredDescription
successnoTrue when the assignment was removed.
{"signatures":{"go":"func (x *CatalogClient) UnassignModelFromProject(ctx context.Context, req *catalogv1.UnassignModelFromProjectRequest) (*catalogv1.UnassignModelFromProjectResponse, error)","python":"unassign_model_from_project(req: catalog_pb2.UnassignModelFromProjectRequest) -\u003e UnassignModelFromProjectResponse","typescript":"unassignModelFromProject(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.UnassignModelFromProjectRequestSchema\u003e): Promise\u003cUnassignModelFromProjectResponse\u003e","cli":"tare api project models remove --model-id $MODEL_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.UnassignModelFromProjectRequest{}\n\n\tresp, err := client.Catalog().UnassignModelFromProject(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/unassignmodelfromproject\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.UnassignModelFromProjectRequest()\ntry:\n    result = client.catalog.unassign_model_from_project(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.unassignModelFromProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api project models remove --model-id $MODEL_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../models/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/models/{model_id}","slug":"unassign-a-model-from-a-project"}

Record a catalog sync run

Changed in v0.5.0 (new features): The catalog API can now record and read a management plane's catalog sync state: which published catalog version it last read, which one it is actually on, when each happened and who ran it. The same pair is on the admin API, so a scheduled job authenticating with a plane's admin key writes the same record an operator's own run does.

What it does: Persists what the last catalog sync saw and did. A sync runs in the client: it fetches a published catalog, compares it with this management plane and writes the difference. The catalog version that drove a run is only known to that client, and a report-only run changes nothing the server could observe, so a run reports itself here. How the record advances: - checked_at / checked_version advance on every recorded run, including report-only ones. They say when this plane last looked at a published catalog, and which one. - applied_at / applied_version advance only when applied is set, which means the run wrote the catalog and left nothing unwritten. They say which published catalog this plane is actually on. The two together are the drift an operator acts on: the published catalog is at version X, this plane is on version Y, applied N days ago.

Request fields:

FieldRequiredDescription
catalog_versionnoexportedAt of the catalogue this run read, verbatim from the document envelope. May be empty: the field is optional in a published catalogue, and an absent version is reported as absent rather than guessed at.
appliednoTrue only for an --apply run that finished with zero per-entry failures. A dry run and a partial apply both leave applied_version alone.
apply_modenoWhether this run wrote or only reported, independent of whether it succeeded. Records the run's INTENT, so a partial apply is still distinguishable from a dry run in the state.
sourcesnoThe documents read, in the order the run read them.
providers_writtennoProviders written by this run. Ignored unless applied is set.
models_writtennoModels written by this run. Ignored unless applied is set.

Response fields:

FieldRequiredDescription
statenoThe merged record as persisted.
{"signatures":{"go":"func (x *CatalogClient) RecordCatalogSync(ctx context.Context, req *catalogv1.RecordCatalogSyncRequest) (*catalogv1.RecordCatalogSyncResponse, error)","python":"record_catalog_sync(req: catalog_pb2.RecordCatalogSyncRequest) -\u003e RecordCatalogSyncResponse","typescript":"recordCatalogSync(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.RecordCatalogSyncRequestSchema\u003e): Promise\u003cRecordCatalogSyncResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"catalog_version\": \"...\",\n    \"applied\": false,\n    \"apply_mode\": false,\n    \"sources\": [],\n    \"providers_written\": 0,\n    \"models_written\": 0\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.RecordCatalogSyncRequest{}\n\n\tresp, err := client.Catalog().RecordCatalogSync(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/recordcatalogsync\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.RecordCatalogSyncRequest()\ntry:\n    result = client.catalog.record_catalog_sync(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.recordCatalogSync(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"catalog_version\": \"...\",\n    \"applied\": false,\n    \"apply_mode\": false,\n    \"sources\": [],\n    \"providers_written\": 0,\n    \"models_written\": 0\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/catalog/sync-state","slug":"record-a-catalog-sync-run"}

Get the catalog sync state

Changed in v0.5.0 (new features): The catalog API can now record and read a management plane's catalog sync state: which published catalog version it last read, which one it is actually on, when each happened and who ran it. The same pair is on the admin API, so a scheduled job authenticating with a plane's admin key writes the same record an operator's own run does.

What it does: Returns this plane's catalog sync record. Never NotFound: a plane that has never recorded a sync returns a state with both timestamps unset, which is itself the answer -- "no sync has ever run here" is a different and more actionable report than an error.

Request body: None.

Response fields:

FieldRequiredDescription
statenoNever null. A plane that has never recorded a sync returns a state with both timestamps unset.
{"signatures":{"go":"func (x *CatalogClient) GetCatalogSyncState(ctx context.Context, req *catalogv1.GetCatalogSyncStateRequest) (*catalogv1.GetCatalogSyncStateResponse, error)","python":"get_catalog_sync_state(req: catalog_pb2.GetCatalogSyncStateRequest) -\u003e GetCatalogSyncStateResponse","typescript":"getCatalogSyncState(req: MessageInitShape\u003ctypeof tars_catalog_v1_catalog_pb.GetCatalogSyncStateRequestSchema\u003e): Promise\u003cGetCatalogSyncStateResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tcatalogv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/catalog/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026catalogv1.GetCatalogSyncStateRequest{}\n\n\tresp, err := client.Catalog().GetCatalogSyncState(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/catalog/getcatalogsyncstate\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.catalog.v1 import catalog_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = catalog_pb2.GetCatalogSyncStateRequest()\ntry:\n    result = client.catalog.get_catalog_sync_state(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.catalog.getCatalogSyncState(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"catalog\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/catalog/sync-state","slug":"get-the-catalog-sync-state"}