Admin

Package: agentrouter.admin.v1 Service: AdminService

Endpoints

Ping

What it does: Endpoint for health checks and authentication testing

Request body: None.

Response fields:

FieldRequiredDescription
messagenoHuman-readable status message (e.g. "pong").
timestampnoServer time when the ping was handled.
{"signatures":{"go":"func (x *AdminClient) Ping(ctx context.Context, req *adminv1.PingRequest) (*adminv1.PingResponse, error)","python":"ping(req: admin_pb2.PingRequest) -\u003e PingResponse","typescript":"ping(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.PingRequestSchema\u003e): Promise\u003cPingResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/ping\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.PingRequest{}\n\n\tresp, err := client.Admin().Ping(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/admin/ping\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.admin.v1 import admin_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 = admin_pb2.PingRequest()\ntry:\n    result = client.admin.ping(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.admin.ping(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/ping\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/ping","slug":"ping"}

Create workspace

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Deprecated Use AdminService.CreateDataplane instead.

What it does: Create workspace

Request fields:

FieldRequiredDescription
customer_idnoCustomer (tenant) slug that will own the workspace.
workspace_idnoCaller-chosen workspace slug, unique within the customer.
namenoOptional human-readable display name.
descriptionnoOptional free-text description.
labelsnoOptional user-defined key/value labels for organization/filtering.
project_idnoOptional project this workspace belongs to. Empty = default project.

Response fields:

FieldRequiredDescription
workspacenoThe newly created workspace.
{"signatures":{"go":"func (x *AdminClient) CreateWorkspace(ctx context.Context, req *adminv1.CreateWorkspaceRequest) (*adminv1.CreateWorkspaceResponse, error)","python":"create_workspace(req: admin_pb2.CreateWorkspaceRequest) -\u003e CreateWorkspaceResponse","typescript":"createWorkspace(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateWorkspaceRequestSchema\u003e): Promise\u003cCreateWorkspaceResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateWorkspaceRequest{}\n\n\tresp, err := client.Admin().CreateWorkspace(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/admin/createworkspace\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.admin.v1 import admin_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 = admin_pb2.CreateWorkspaceRequest()\ntry:\n    result = client.admin.create_workspace(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.admin.createWorkspace(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/workspaces\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/workspaces","slug":"create-workspace"}

List workspaces

Changed in v0.11.0 (bug fixes): Listing data planes now returns next_page_token when more remain, and passing it as page_token returns the next page. A token that is malformed or from a listing for another customer is refused with INVALID_ARGUMENT. Configuration changes now reach every data plane of a customer with more than 1,000 of them.

Deprecated Use AdminService.ListDataplanes instead.

What it does: List workspaces

Request fields:

FieldRequiredDescription
customer_idnoOptional filter: only return workspaces owned by this customer slug.
page_sizenoMax workspaces to return per page (0 = server default).
page_tokennoOpaque cursor from a previous response's next_page_token.

Response fields:

FieldRequiredDescription
workspacesnoPage of matching workspaces.
next_page_tokennoCursor for the next page; empty when there are no more results.
{"signatures":{"go":"func (x *AdminClient) ListWorkspaces(ctx context.Context, req *adminv1.ListWorkspacesRequest) (*adminv1.ListWorkspacesResponse, error)","python":"list_workspaces(req: admin_pb2.ListWorkspacesRequest) -\u003e ListWorkspacesResponse","typescript":"listWorkspaces(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListWorkspacesRequestSchema\u003e): Promise\u003cListWorkspacesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListWorkspacesRequest{}\n\n\tresp, err := client.Admin().ListWorkspaces(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/admin/listworkspaces\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.admin.v1 import admin_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 = admin_pb2.ListWorkspacesRequest()\ntry:\n    result = client.admin.list_workspaces(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.admin.listWorkspaces(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/workspaces\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/workspaces","slug":"list-workspaces"}

Get workspace

Deprecated Use AdminService.GetDataplane instead.

What it does: Get workspace

Request fields:

FieldRequiredDescription
idnoWorkspace UUID (the internal id, not the customer-chosen workspace_id).

Response fields:

FieldRequiredDescription
workspacenoThe requested workspace.
{"signatures":{"go":"func (x *AdminClient) GetWorkspace(ctx context.Context, req *adminv1.GetWorkspaceRequest) (*adminv1.GetWorkspaceResponse, error)","python":"get_workspace(req: admin_pb2.GetWorkspaceRequest) -\u003e GetWorkspaceResponse","typescript":"getWorkspace(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetWorkspaceRequestSchema\u003e): Promise\u003cGetWorkspaceResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetWorkspaceRequest{}\n\n\tresp, err := client.Admin().GetWorkspace(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/admin/getworkspace\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.admin.v1 import admin_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 = admin_pb2.GetWorkspaceRequest()\ntry:\n    result = client.admin.get_workspace(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.admin.getWorkspace(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/workspaces/{id}","slug":"get-workspace"}

Update workspace

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Changed in v0.7.0 (new features): A data plane can now repair itself when its doctor reports RBAC objects or CRDs its chart declares as missing or changed, writing back what the chart says. Turn it on per data plane with auto_repair. A run makes at most two attempts, and the data plane's health then shows a SelfRepairHealthy issue carrying the error. A run that escalates also keeps a doctor bundle, which happens when both attempts fail on the same step or the data plane reports on neither.

Deprecated Use AdminService.UpdateDataplane instead.

What it does: Update workspace

Request fields:

FieldRequiredDescription
idnoWorkspace UUID to update.
namenoNew display name; unset leaves the existing value.
descriptionnoNew description; unset leaves the existing value.
labelsnoReplacement set of labels.
auto_upgradenoFlip unattended upgrades on or off; unset leaves the existing value.
auto_repairnoFlip unattended self-repair on or off; unset leaves the existing value.

Response fields:

FieldRequiredDescription
workspacenoThe updated workspace.
{"signatures":{"go":"func (x *AdminClient) UpdateWorkspace(ctx context.Context, req *adminv1.UpdateWorkspaceRequest) (*adminv1.UpdateWorkspaceResponse, error)","python":"update_workspace(req: admin_pb2.UpdateWorkspaceRequest) -\u003e UpdateWorkspaceResponse","typescript":"updateWorkspace(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateWorkspaceRequestSchema\u003e): Promise\u003cUpdateWorkspaceResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"auto_upgrade\": false,\n    \"auto_repair\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateWorkspaceRequest{}\n\n\tresp, err := client.Admin().UpdateWorkspace(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/admin/updateworkspace\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.admin.v1 import admin_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 = admin_pb2.UpdateWorkspaceRequest()\ntry:\n    result = client.admin.update_workspace(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.admin.updateWorkspace(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"auto_upgrade\": false,\n    \"auto_repair\": false\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/workspaces/{id}","slug":"update-workspace"}

Set workspace URL

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Changed in v0.8.0 (security updates): SetWorkspaceURL and SetDataplaneURL refuse to set or clear a data plane URL with FailedPrecondition when another organization uses the same data plane ID. The URL was stored under the ID alone, so the write also changed the other organization's data plane. CreateServiceAccount with a serve URL for such an ID is refused too when no URL is stored for that ID yet. The Admin Console's System Settings save does not check this yet; it moves onto SetDataplaneURL in a later release.

Changed in v0.7.0 (deprecations): Setting a data plane's or a project gateway's address through the admin API is deprecated. A 0.7 data plane reports its own address from global.gateway.hostnames in its serve-helm values. SetDataplaneURL, its SetWorkspaceURL alias, SetProjectGatewayURL and the url field of CreateProjectGateway and UpdateProjectGateway keep working. A data plane before 0.7 cannot declare hostnames, so these calls stay until no supported data plane predates 0.7.

Changed in v0.4.0 (security updates): Claiming a hostname that is already in use no longer exposes details about the existing configuration. The conflict message now says only that the hostname is in use, preventing a rejected claim from revealing information about another organization's resources.

Deprecated Use AdminService.SetDataplaneURL instead.

What it does: Set the customer-facing gateway URL for a workspace data plane. Writes system_settings.dataplane-url:<workspace_id> and optionally fires a PROXY_URL config event. Deprecated (fraser#8586): SetDataplaneURL, which superseded this call, is deprecated too. A data plane reports its own address from global.gateway.hostnames in its serve-helm values, and the management plane mirrors it read-only. This stays working in 0.6; removal is proposed for 0.8.

Request fields:

FieldRequiredDescription
idnoWorkspace UUID whose data-plane URL is being set.
urlnourl is the full https:// URL of the data plane's customer-facing gateway endpoint.
trigger_updatenotrigger_update fires a PROXY_URL config event to the data plane after persisting the URL.

Response fields:

FieldRequiredDescription
workspacenoThe workspace reflecting the new data-plane URL.
{"signatures":{"go":"func (x *AdminClient) SetWorkspaceURL(ctx context.Context, req *adminv1.SetWorkspaceURLRequest) (*adminv1.SetWorkspaceURLResponse, error)","python":"set_workspace_url(req: admin_pb2.SetWorkspaceURLRequest) -\u003e SetWorkspaceURLResponse","typescript":"setWorkspaceURL(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetWorkspaceURLRequestSchema\u003e): Promise\u003cSetWorkspaceURLResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"trigger_update\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetWorkspaceURLRequest{}\n\n\tresp, err := client.Admin().SetWorkspaceURL(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/admin/setworkspaceurl\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.admin.v1 import admin_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 = admin_pb2.SetWorkspaceURLRequest()\ntry:\n    result = client.admin.set_workspace_url(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.admin.setWorkspaceURL(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/workspaces/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"trigger_update\": false\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/workspaces/{id}/url","slug":"set-workspace-url"}

Set workspace project

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Deprecated Use AdminService.SetDataplaneProject instead.

What it does: Assign workspace to a project (or clear back to default project by omitting project_id)

Request fields:

FieldRequiredDescription
idnoWorkspace UUID to reassign.
project_idnoproject_id to assign. Omit or set to empty string to clear back to the default project (NULL).

Response fields:

FieldRequiredDescription
workspacenoThe workspace with its updated project assignment.
{"signatures":{"go":"func (x *AdminClient) SetWorkspaceProject(ctx context.Context, req *adminv1.SetWorkspaceProjectRequest) (*adminv1.SetWorkspaceProjectResponse, error)","python":"set_workspace_project(req: admin_pb2.SetWorkspaceProjectRequest) -\u003e SetWorkspaceProjectResponse","typescript":"setWorkspaceProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetWorkspaceProjectRequestSchema\u003e): Promise\u003cSetWorkspaceProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H.../project\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetWorkspaceProjectRequest{}\n\n\tresp, err := client.Admin().SetWorkspaceProject(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/admin/setworkspaceproject\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.admin.v1 import admin_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 = admin_pb2.SetWorkspaceProjectRequest()\ntry:\n    result = client.admin.set_workspace_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.admin.setWorkspaceProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/workspaces/01H.../project\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/workspaces/{id}/project","slug":"set-workspace-project"}

Delete workspace

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Changed in v0.7.0 (behaviour changes): Deleting a data plane now refuses while it is the only one serving a project, and the refusal names up to ten of those projects and reports how many there are in all. A data plane whose projects are all served by another one is deleted as before. Detaching a project from its last data plane is still allowed and now writes a PROJECT_SERVED_NOWHERE audit entry naming the project and that data plane, so the audit log carries a new action type from this release on.

Deprecated Use AdminService.DeleteDataplane instead.

What it does: Delete workspace (soft delete)

Request fields:

FieldRequiredDescription
idnoWorkspace UUID to soft-delete.

Response fields:

FieldRequiredDescription
successnoTrue if the workspace was deleted.
deleted_atnoWhen the soft delete took effect.
{"signatures":{"go":"func (x *AdminClient) DeleteWorkspace(ctx context.Context, req *adminv1.DeleteWorkspaceRequest) (*adminv1.DeleteWorkspaceResponse, error)","python":"delete_workspace(req: admin_pb2.DeleteWorkspaceRequest) -\u003e DeleteWorkspaceResponse","typescript":"deleteWorkspace(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteWorkspaceRequestSchema\u003e): Promise\u003cDeleteWorkspaceResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteWorkspaceRequest{}\n\n\tresp, err := client.Admin().DeleteWorkspace(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/admin/deleteworkspace\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.admin.v1 import admin_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 = admin_pb2.DeleteWorkspaceRequest()\ntry:\n    result = client.admin.delete_workspace(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.admin.deleteWorkspace(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/workspaces/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/workspaces/{id}","slug":"delete-workspace"}

Create dataplane

What it does: Register a data plane.

Request fields:

FieldRequiredDescription
customer_idnoCustomer (tenant) slug that will own the data plane.
dataplane_idnoCaller-chosen data plane slug, unique within the customer.
namenoOptional human-readable display name.
descriptionnoOptional free-text description.
labelsnoOptional user-defined key/value labels.
project_idnoOptional project this data plane belongs to. Empty = default project.

Response fields:

FieldRequiredDescription
dataplanenoundocumented
{"signatures":{"go":"func (x *AdminClient) CreateDataplane(ctx context.Context, req *adminv1.CreateDataplaneRequest) (*adminv1.CreateDataplaneResponse, error)","python":"create_dataplane(req: admin_pb2.CreateDataplaneRequest) -\u003e CreateDataplaneResponse","typescript":"createDataplane(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateDataplaneRequestSchema\u003e): Promise\u003cCreateDataplaneResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"dataplane_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateDataplaneRequest{}\n\n\tresp, err := client.Admin().CreateDataplane(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/admin/createdataplane\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.admin.v1 import admin_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 = admin_pb2.CreateDataplaneRequest()\ntry:\n    result = client.admin.create_dataplane(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.admin.createDataplane(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"dataplane_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/dataplanes","slug":"create-dataplane"}

List dataplanes

Changed in v0.11.0 (bug fixes): Listing data planes now returns next_page_token when more remain, and passing it as page_token returns the next page. A token that is malformed or from a listing for another customer is refused with INVALID_ARGUMENT. Configuration changes now reach every data plane of a customer with more than 1,000 of them.

Changed in v0.9.0 (new features): Data planes now carry stored_url, the URL stored for the data plane. When another organization uses the same data plane ID, stored_url is the first hostname your data plane declares, or empty. The new ClearSystemSetting unsets the proxy URL setting or the stored URL of one data plane.

Changed in v0.9.0 (deprecations): stored_url on data planes and ClearSystemSetting are deprecated. They go with the stored data plane URL in a later release.

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

What it does: List data planes.

Request fields:

FieldRequiredDescription
customer_idnoundocumented
page_sizenoundocumented
page_tokennoundocumented

Response fields:

FieldRequiredDescription
dataplanesnoundocumented
next_page_tokennoundocumented
{"signatures":{"go":"func (x *AdminClient) ListDataplanes(ctx context.Context, req *adminv1.ListDataplanesRequest) (*adminv1.ListDataplanesResponse, error)","python":"list_dataplanes(req: admin_pb2.ListDataplanesRequest) -\u003e ListDataplanesResponse","typescript":"listDataplanes(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListDataplanesRequestSchema\u003e): Promise\u003cListDataplanesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListDataplanesRequest{}\n\n\tresp, err := client.Admin().ListDataplanes(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/admin/listdataplanes\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.admin.v1 import admin_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 = admin_pb2.ListDataplanesRequest()\ntry:\n    result = client.admin.list_dataplanes(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.admin.listDataplanes(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/dataplanes","slug":"list-dataplanes"}

Get dataplane

Changed in v0.9.0 (new features): Data planes now carry stored_url, the URL stored for the data plane. When another organization uses the same data plane ID, stored_url is the first hostname your data plane declares, or empty. The new ClearSystemSetting unsets the proxy URL setting or the stored URL of one data plane.

Changed in v0.9.0 (deprecations): stored_url on data planes and ClearSystemSetting are deprecated. They go with the stored data plane URL in a later release.

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

What it does: Get a data plane.

Request fields:

FieldRequiredDescription
idnoundocumented

Response fields:

FieldRequiredDescription
dataplanenoundocumented
{"signatures":{"go":"func (x *AdminClient) GetDataplane(ctx context.Context, req *adminv1.GetDataplaneRequest) (*adminv1.GetDataplaneResponse, error)","python":"get_dataplane(req: admin_pb2.GetDataplaneRequest) -\u003e GetDataplaneResponse","typescript":"getDataplane(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetDataplaneRequestSchema\u003e): Promise\u003cGetDataplaneResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetDataplaneRequest{}\n\n\tresp, err := client.Admin().GetDataplane(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/admin/getdataplane\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.admin.v1 import admin_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 = admin_pb2.GetDataplaneRequest()\ntry:\n    result = client.admin.get_dataplane(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.admin.getDataplane(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/dataplanes/{id}","slug":"get-dataplane"}

Update dataplane

Changed in v0.7.0 (new features): A data plane can now repair itself when its doctor reports RBAC objects or CRDs its chart declares as missing or changed, writing back what the chart says. Turn it on per data plane with auto_repair. A run makes at most two attempts, and the data plane's health then shows a SelfRepairHealthy issue carrying the error. A run that escalates also keeps a doctor bundle, which happens when both attempts fail on the same step or the data plane reports on neither.

What it does: Update a data plane.

Request fields:

FieldRequiredDescription
idnoundocumented
namenoundocumented
descriptionnoundocumented
labelsnoundocumented
auto_upgradenoMirrors UpdateWorkspaceRequest.auto_upgrade.
auto_repairnoMirrors UpdateWorkspaceRequest.auto_repair.

Response fields:

FieldRequiredDescription
dataplanenoundocumented
{"signatures":{"go":"func (x *AdminClient) UpdateDataplane(ctx context.Context, req *adminv1.UpdateDataplaneRequest) (*adminv1.UpdateDataplaneResponse, error)","python":"update_dataplane(req: admin_pb2.UpdateDataplaneRequest) -\u003e UpdateDataplaneResponse","typescript":"updateDataplane(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateDataplaneRequestSchema\u003e): Promise\u003cUpdateDataplaneResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"auto_upgrade\": false,\n    \"auto_repair\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateDataplaneRequest{}\n\n\tresp, err := client.Admin().UpdateDataplane(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/admin/updatedataplane\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.admin.v1 import admin_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 = admin_pb2.UpdateDataplaneRequest()\ntry:\n    result = client.admin.update_dataplane(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.admin.updateDataplane(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"auto_upgrade\": false,\n    \"auto_repair\": false\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/dataplanes/{id}","slug":"update-dataplane"}

Set dataplane URL

Changed in v0.8.0 (security updates): SetWorkspaceURL and SetDataplaneURL refuse to set or clear a data plane URL with FailedPrecondition when another organization uses the same data plane ID. The URL was stored under the ID alone, so the write also changed the other organization's data plane. CreateServiceAccount with a serve URL for such an ID is refused too when no URL is stored for that ID yet. The Admin Console's System Settings save does not check this yet; it moves onto SetDataplaneURL in a later release.

Changed in v0.7.0 (deprecations): Setting a data plane's or a project gateway's address through the admin API is deprecated. A 0.7 data plane reports its own address from global.gateway.hostnames in its serve-helm values. SetDataplaneURL, its SetWorkspaceURL alias, SetProjectGatewayURL and the url field of CreateProjectGateway and UpdateProjectGateway keep working. A data plane before 0.7 cannot declare hostnames, so these calls stay until no supported data plane predates 0.7.

Changed in v0.4.0 (security updates): Claiming a hostname that is already in use no longer exposes details about the existing configuration. The conflict message now says only that the hostname is in use, preventing a rejected claim from revealing information about another organization's resources.

Deprecated

What it does: Set the customer-facing advertised URL for a data plane. Deprecated (fraser#8586): a data plane reports its own address from global.gateway.hostnames in its serve-helm values, and the management plane mirrors it read-only. This stays working in 0.6; removal is proposed for 0.8.

Request fields:

FieldRequiredDescription
idnoundocumented
urlnoundocumented
trigger_updatenoundocumented

Response fields:

FieldRequiredDescription
dataplanenoundocumented
{"signatures":{"go":"func (x *AdminClient) SetDataplaneURL(ctx context.Context, req *adminv1.SetDataplaneURLRequest) (*adminv1.SetDataplaneURLResponse, error)","python":"set_dataplane_url(req: admin_pb2.SetDataplaneURLRequest) -\u003e SetDataplaneURLResponse","typescript":"setDataplaneURL(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetDataplaneURLRequestSchema\u003e): Promise\u003cSetDataplaneURLResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"trigger_update\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetDataplaneURLRequest{}\n\n\tresp, err := client.Admin().SetDataplaneURL(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/admin/setdataplaneurl\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.admin.v1 import admin_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 = admin_pb2.SetDataplaneURLRequest()\ntry:\n    result = client.admin.set_dataplane_url(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.admin.setDataplaneURL(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"trigger_update\": false\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/dataplanes/{id}/url","slug":"set-dataplane-url"}

Set dataplane project

What it does: Assign a data plane to a project (omit project_id to clear to default).

Request fields:

FieldRequiredDescription
idnoundocumented
project_idnoundocumented

Response fields:

FieldRequiredDescription
dataplanenoundocumented
{"signatures":{"go":"func (x *AdminClient) SetDataplaneProject(ctx context.Context, req *adminv1.SetDataplaneProjectRequest) (*adminv1.SetDataplaneProjectResponse, error)","python":"set_dataplane_project(req: admin_pb2.SetDataplaneProjectRequest) -\u003e SetDataplaneProjectResponse","typescript":"setDataplaneProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetDataplaneProjectRequestSchema\u003e): Promise\u003cSetDataplaneProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../project\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetDataplaneProjectRequest{}\n\n\tresp, err := client.Admin().SetDataplaneProject(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/admin/setdataplaneproject\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.admin.v1 import admin_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 = admin_pb2.SetDataplaneProjectRequest()\ntry:\n    result = client.admin.set_dataplane_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.admin.setDataplaneProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../project\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/dataplanes/{id}/project","slug":"set-dataplane-project"}

List dataplane projects

Changed in v0.7.0 (new features): A data plane can now be labelled with the projects it serves, naming a data plane and a project rather than a gateway. The data plane picks that project's configuration up on its next config update, and drops it on the next one after the label is removed. Removing the last label serving a project is refused, because its keys would then admit nowhere, unless the call sets acknowledge_last_endpoint to remove it anyway; the response then reports served_nowhere so the caller can tell its owners.

Changed in v0.7.0 (new features): Each project label now says when that data plane first answered a request for the project successfully, in a new verified_at field. It is per project and data plane, so another project's traffic on the same data plane never sets it, and applying a label again clears it until the next success. Each label also reports the config pull before it, as target_revision, held_revision and config_current.

What it does: List the labels a customer holds, which are the (data plane, project) pairs recording which projects each data plane serves (fraser#8587). A label is the project itself selected on a data plane, so it has no lifecycle of its own and there is nothing here to create or name. Filter by dataplane_id for one data plane's own record, by project_id for the data planes serving one project, or by neither for the whole customer, which answers both directions in one request. The answer comes from dataplane_projects rather than from the project gateway join, so a data plane that has never converged still reads as serving what it is labelled with: the question is which projects the management plane distributes to it, not which ones it has already pulled.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
dataplane_idnoOptional filter: only the labels this data plane carries.
project_idnoOptional filter: only the data planes serving this project.

Response fields:

FieldRequiredDescription
labelsnoundocumented
{"signatures":{"go":"func (x *AdminClient) ListDataplaneProjects(ctx context.Context, req *adminv1.ListDataplaneProjectsRequest) (*adminv1.ListDataplaneProjectsResponse, error)","python":"list_dataplane_projects(req: admin_pb2.ListDataplaneProjectsRequest) -\u003e ListDataplaneProjectsResponse","typescript":"listDataplaneProjects(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListDataplaneProjectsRequestSchema\u003e): Promise\u003cListDataplaneProjectsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplane-projects\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListDataplaneProjectsRequest{}\n\n\tresp, err := client.Admin().ListDataplaneProjects(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/admin/listdataplaneprojects\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.admin.v1 import admin_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 = admin_pb2.ListDataplaneProjectsRequest()\ntry:\n    result = client.admin.list_dataplane_projects(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.admin.listDataplaneProjects(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../dataplane-projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/dataplane-projects","slug":"list-dataplane-projects"}

Add dataplane project

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.10.0 (behaviour changes): Writing a project's OIDC contract is refused on Agent Router Service (SaaS). Enabling a contract is refused while a data plane serving the project runs a build older than 0.10.0 or has not reported its build, and so is attaching a project whose contract is enabled to such a data plane. Each refusal names the data plane.

Changed in v0.7.0 (new features): A data plane can now be labelled with the projects it serves, naming a data plane and a project rather than a gateway. The data plane picks that project's configuration up on its next config update, and drops it on the next one after the label is removed. Removing the last label serving a project is refused, because its keys would then admit nowhere, unless the call sets acknowledge_last_endpoint to remove it anyway; the response then reports served_nowhere so the caller can tell its owners.

What it does: Label a data plane with a project, so it serves that project's configuration from its next config update (fraser#8591). Idempotent: labelling a data plane that already serves the project leaves the label alone and reports the same success. The project's keys admit on this data plane once its pull lands, not when this call returns, and neither the project nor any other data plane serving it is modified. No hostname, DNS record or certificate takes part. Labelling a data plane with a SECOND project needs that data plane to host more than one project gateway, and this refuses with FAILED_PRECONDITION naming the reason while it hosts a single one.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
dataplane_idnoData plane to label.
project_idnoProject the data plane is to serve. It must already exist: a label is the project itself, so nothing here creates one.

Response fields:

FieldRequiredDescription
labelsnoThe data plane's labels after the call, so a caller renders the new set without a second read.
warningsnoConditions that leave the label true but unserved, such as a project with no models enabled. Carried from the underlying attach.
{"signatures":{"go":"func (x *AdminClient) AddDataplaneProject(ctx context.Context, req *adminv1.AddDataplaneProjectRequest) (*adminv1.AddDataplaneProjectResponse, error)","python":"add_dataplane_project(req: admin_pb2.AddDataplaneProjectRequest) -\u003e AddDataplaneProjectResponse","typescript":"addDataplaneProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AddDataplaneProjectRequestSchema\u003e): Promise\u003cAddDataplaneProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplanes/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AddDataplaneProjectRequest{}\n\n\tresp, err := client.Admin().AddDataplaneProject(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/admin/adddataplaneproject\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.admin.v1 import admin_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 = admin_pb2.AddDataplaneProjectRequest()\ntry:\n    result = client.admin.add_dataplane_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.admin.addDataplaneProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../dataplanes/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/dataplanes/{dataplane_id}/projects","slug":"add-dataplane-project"}

Remove dataplane project

Changed in v0.7.0 (new features): A data plane can now be labelled with the projects it serves, naming a data plane and a project rather than a gateway. The data plane picks that project's configuration up on its next config update, and drops it on the next one after the label is removed. Removing the last label serving a project is refused, because its keys would then admit nowhere, unless the call sets acknowledge_last_endpoint to remove it anyway; the response then reports served_nowhere so the caller can tell its owners.

Changed in v0.7.0 (bug fixes): Removing the last project from a data plane that has a single gateway now takes the project's label off, reports served_nowhere and records PROJECT_SERVED_NOWHERE in the audit log. Before, the call answered removed=true while the label stayed on the data plane, and neither was recorded.

Changed in v0.7.0 (bug fixes): Removing a project from a data plane now takes the label off even when the data plane's configuration update fails, so a response with removed=true no longer lists the label it removed. Removing a label left behind by an earlier removal records PROJECT_SERVED_NOWHERE when it was the project's last one.

What it does: Remove a project's label from a data plane, which clears that project's configuration there on its next update (fraser#8591). Removing a label another data plane also carries costs the project nothing. Removing the last one takes the project's last endpoint away, so this RPC refuses that case with FAILED_PRECONDITION naming the project (fraser#9425): label another data plane with it first, or remove the label deliberately through the path that tells its owners. Removing a label the data plane does not carry is an idempotent no-op reporting removed=false. Until the data plane's next pull lands it still holds the old configuration and the project's keys still admit there.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
dataplane_idnoData plane to take the label off.
project_idnoProject to stop serving here.
acknowledge_last_endpointnoThe caller has been told this data plane is the last one serving the project and chose to leave it served by nothing. Without this, a removal that would strand the project is refused (fraser#9425); with it, the removal proceeds and the outcome is recorded (see RemoveDataplaneProjectResponse.served_nowhere and the PROJECT_SERVED_NOWHERE audit action) so the project's owners are told rather than finding out when their keys stop working.

Response fields:

FieldRequiredDescription
removednoFalse when the data plane carried no such label, which is a no-op rather than an error.
labelsnoThe data plane's labels after the call.
served_nowherenoTrue when this removal left the project served by no data plane at all. Set only when removed is also true; the console reads this instead of inferring it, so it can say so directly rather than the operator discovering it when the project's keys stop working.
{"signatures":{"go":"func (x *AdminClient) RemoveDataplaneProject(ctx context.Context, req *adminv1.RemoveDataplaneProjectRequest) (*adminv1.RemoveDataplaneProjectResponse, error)","python":"remove_dataplane_project(req: admin_pb2.RemoveDataplaneProjectRequest) -\u003e RemoveDataplaneProjectResponse","typescript":"removeDataplaneProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RemoveDataplaneProjectRequestSchema\u003e): Promise\u003cRemoveDataplaneProjectResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplanes/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RemoveDataplaneProjectRequest{}\n\n\tresp, err := client.Admin().RemoveDataplaneProject(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/admin/removedataplaneproject\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.admin.v1 import admin_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 = admin_pb2.RemoveDataplaneProjectRequest()\ntry:\n    result = client.admin.remove_dataplane_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.admin.removeDataplaneProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplanes/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/dataplanes/{dataplane_id}/projects/{project_id}","slug":"remove-dataplane-project"}

Delete dataplane

Changed in v0.7.0 (behaviour changes): Deleting a data plane now refuses while it is the only one serving a project, and the refusal names up to ten of those projects and reports how many there are in all. A data plane whose projects are all served by another one is deleted as before. Detaching a project from its last data plane is still allowed and now writes a PROJECT_SERVED_NOWHERE audit entry naming the project and that data plane, so the audit log carries a new action type from this release on.

Changed in v0.7.0 (new features): Forgetting a data plane now leaves a zeroize directive waiting for it and soft-deletes its credential. The directive travels only on the data plane's own next configuration poll, which the record shows as a call home, and the data plane acknowledges it like any configuration revision. A data plane that never calls keeps serving what it holds, and the forget can be undone until the directive lands. A data plane that was issued a new credential before it was forgotten collects its directive too.

What it does: Delete a data plane (soft delete).

Request fields:

FieldRequiredDescription
idnoundocumented

Response fields:

FieldRequiredDescription
successnoundocumented
deleted_atnoundocumented
{"signatures":{"go":"func (x *AdminClient) DeleteDataplane(ctx context.Context, req *adminv1.DeleteDataplaneRequest) (*adminv1.DeleteDataplaneResponse, error)","python":"delete_dataplane(req: admin_pb2.DeleteDataplaneRequest) -\u003e DeleteDataplaneResponse","typescript":"deleteDataplane(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteDataplaneRequestSchema\u003e): Promise\u003cDeleteDataplaneResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteDataplaneRequest{}\n\n\tresp, err := client.Admin().DeleteDataplane(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/admin/deletedataplane\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.admin.v1 import admin_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 = admin_pb2.DeleteDataplaneRequest()\ntry:\n    result = client.admin.delete_dataplane(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.admin.deleteDataplane(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/dataplanes/{id}","slug":"delete-dataplane"}

List dataplane config overrides

Changed in v0.7.0 (behaviour changes): A provider endpoint or key override now applies to one project on a data plane and names that project, so another project the same data plane serves keeps calling the provider with the bundle endpoint and credential. An override written before this release named no project and is removed, with its stored credential, the first time the management plane starts after the upgrade.

Changed in v0.7.0 (new features): An administrator can now give one project on one data plane its own endpoint or its own key for one provider, and every other project that data plane serves goes on calling the provider with the bundle endpoint and credential. A key is write-only and reaches only the project it was written for; clearing an override restores the bundle value and destroys the key.

What it does: List the whitelisted overrides one data plane carries, for one project or for every project. A key override reports only that a credential is set: no read path on this service returns key material.

Request fields:

FieldRequiredDescription
idnoServer-generated data plane UUID, the id a Dataplane carries. The owning customer is the data plane's own, so the request names none.
project_idnoNarrows the list to one project. Empty lists every project's overrides.

Response fields:

FieldRequiredDescription
overridesnoThe overrides this data plane carries, ordered by project and then by canonical field path.
project_scopednoAlways true from a management plane that keys overrides on the project. A caller reads it to tell that build from an older one, which ignores the request's project_id, lists overrides that reach every project on the data plane, and would store a write as one that reaches every project too.
{"signatures":{"go":"func (x *AdminClient) ListDataplaneConfigOverrides(ctx context.Context, req *adminv1.ListDataplaneConfigOverridesRequest) (*adminv1.ListDataplaneConfigOverridesResponse, error)","python":"list_dataplane_config_overrides(req: admin_pb2.ListDataplaneConfigOverridesRequest) -\u003e ListDataplaneConfigOverridesResponse","typescript":"listDataplaneConfigOverrides(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListDataplaneConfigOverridesRequestSchema\u003e): Promise\u003cListDataplaneConfigOverridesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../config-overrides\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListDataplaneConfigOverridesRequest{}\n\n\tresp, err := client.Admin().ListDataplaneConfigOverrides(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/admin/listdataplaneconfigoverrides\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.admin.v1 import admin_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 = admin_pb2.ListDataplaneConfigOverridesRequest()\ntry:\n    result = client.admin.list_dataplane_config_overrides(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.admin.listDataplaneConfigOverrides(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../config-overrides\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/dataplanes/{id}/config-overrides","slug":"list-dataplane-config-overrides"}

Set dataplane config override

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.7.0 (behaviour changes): A provider endpoint or key override now applies to one project on a data plane and names that project, so another project the same data plane serves keeps calling the provider with the bundle endpoint and credential. An override written before this release named no project and is removed, with its stored credential, the first time the management plane starts after the upgrade.

Changed in v0.7.0 (new features): An administrator can now give one project on one data plane its own endpoint or its own key for one provider, and every other project that data plane serves goes on calling the provider with the bundle endpoint and credential. A key is write-only and reaches only the project it was written for; clearing an override restores the bundle value and destroys the key.

What it does: Override one whitelisted field on one data plane. Exactly one of value and key carries the override, and which one is decided by the field path: providers.<provider>.endpoint takes value, and providers.<provider>.key takes key. A field path outside the whitelist is rejected with INVALID_ARGUMENT naming the two paths a provider offers. A repeat write replaces the value the field held. Every write lands in the audit log with the field path, the data plane and the actor, and the data plane it names regenerates its configuration, so it carries the override on its next pull. A credential is stored write-only: it goes to the secret service and the override keeps a reference the data plane resolves, which resolves for that data plane alone. A write needs the project labelled on the data plane, and answers FAILED_PRECONDITION naming both when it is not: label the project onto the data plane first. A project that does not exist answers NOT_FOUND. A write to an external provider is refused for both fields, and a credential override for a provider whose auth type is none is refused, because a data plane never reads a credential for that provider. A data plane below the version that renders per-project provider objects is refused for both fields. An override reaches the project's requests on every route family the data plane serves it through: the shared catalog routes, the fallback chains and the routes of the project's own keys. A request authenticated with a key the caller brought themselves (BYOK) keeps dialling the bundle endpoint with the caller's key. On a deployment that registers an external autofallback-<provider> catalog entry, the primary leg routed through that service is not covered.

Request fields:

FieldRequiredDescription
idnoServer-generated data plane UUID, the id a Dataplane carries. The owning customer is the data plane's own, so the request names none.
field_pathnoThe whitelisted field, e.g. "providers.openai.endpoint". Case and provider spelling are normalized, so PROVIDERS.AWS-BEDROCK.ENDPOINT and providers.awsbedrock.endpoint name one field.
valuenoThe address to call the provider on, for an endpoint field. It carries a scheme, because the data plane decides TLS and the port from it.
keynoThe credential, for a key field. Write-only: no read path returns it.
project_idnoThe project the override applies to. It has to be labelled on the data plane.

Response fields:

FieldRequiredDescription
overridenoThe stored override, with a key reported as set rather than returned.
{"signatures":{"go":"func (x *AdminClient) SetDataplaneConfigOverride(ctx context.Context, req *adminv1.SetDataplaneConfigOverrideRequest) (*adminv1.SetDataplaneConfigOverrideResponse, error)","python":"set_dataplane_config_override(req: admin_pb2.SetDataplaneConfigOverrideRequest) -\u003e SetDataplaneConfigOverrideResponse","typescript":"setDataplaneConfigOverride(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetDataplaneConfigOverrideRequestSchema\u003e): Promise\u003cSetDataplaneConfigOverrideResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../config-overrides\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"field_path\": \"...\",\n    \"value\": \"...\",\n    \"key\": \"...\",\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetDataplaneConfigOverrideRequest{}\n\n\tresp, err := client.Admin().SetDataplaneConfigOverride(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/admin/setdataplaneconfigoverride\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.admin.v1 import admin_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 = admin_pb2.SetDataplaneConfigOverrideRequest()\ntry:\n    result = client.admin.set_dataplane_config_override(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.admin.setDataplaneConfigOverride(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../config-overrides\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"field_path\": \"...\",\n    \"value\": \"...\",\n    \"key\": \"...\",\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/dataplanes/{id}/config-overrides","slug":"set-dataplane-config-override"}

Clear dataplane config override

Changed in v0.7.0 (behaviour changes): A provider endpoint or key override now applies to one project on a data plane and names that project, so another project the same data plane serves keeps calling the provider with the bundle endpoint and credential. An override written before this release named no project and is removed, with its stored credential, the first time the management plane starts after the upgrade.

Changed in v0.7.0 (new features): An administrator can now give one project on one data plane its own endpoint or its own key for one provider, and every other project that data plane serves goes on calling the provider with the bundle endpoint and credential. A key is write-only and reaches only the project it was written for; clearing an override restores the bundle value and destroys the key.

What it does: Clear one project's override of one field, which returns the field to the value the bundle carries for that project. Clearing a field that carries no override reports cleared: false rather than failing. Clearing a credential override also destroys the stored credential, so the reference stops resolving for anyone. The project's requests fall back to the deployment-wide credential once the data plane applies its next pull, which an administrator containing a leaked key has to check is not the leaked one: a clear revokes nothing at the provider.

Request fields:

FieldRequiredDescription
idnoServer-generated data plane UUID, the id a Dataplane carries. The owning customer is the data plane's own, so the request names none.
field_pathnoThe whitelisted field to return to the bundle value.
project_idnoThe project whose override is cleared.

Response fields:

FieldRequiredDescription
clearednoFalse when the field carried no override, which is not an error.
{"signatures":{"go":"func (x *AdminClient) ClearDataplaneConfigOverride(ctx context.Context, req *adminv1.ClearDataplaneConfigOverrideRequest) (*adminv1.ClearDataplaneConfigOverrideResponse, error)","python":"clear_dataplane_config_override(req: admin_pb2.ClearDataplaneConfigOverrideRequest) -\u003e ClearDataplaneConfigOverrideResponse","typescript":"clearDataplaneConfigOverride(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ClearDataplaneConfigOverrideRequestSchema\u003e): Promise\u003cClearDataplaneConfigOverrideResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../config-overrides:clear\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"field_path\": \"...\",\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ClearDataplaneConfigOverrideRequest{}\n\n\tresp, err := client.Admin().ClearDataplaneConfigOverride(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/admin/cleardataplaneconfigoverride\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.admin.v1 import admin_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 = admin_pb2.ClearDataplaneConfigOverrideRequest()\ntry:\n    result = client.admin.clear_dataplane_config_override(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.admin.clearDataplaneConfigOverride(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../config-overrides:clear\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"field_path\": \"...\",\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/dataplanes/{id}/config-overrides:clear","slug":"clear-dataplane-config-override"}

List dataplane config differences

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

What it does: List the configuration differences one data plane reports.

Request fields:

FieldRequiredDescription
idnoData plane id: the server-generated UUID this service returns as Dataplane.id, the same one every sibling RPC on this path space takes. Not Dataplane.dataplane_id, which is the slug an operator reads.
include_clearednoInclude the differences that have already cleared. They carry cleared_at, and they are how an operator sees that something was wrong after it stopped being wrong.
include_acknowledgednoInclude the differences somebody has acknowledged.
page_sizenoMax differences to return per page (0 = server default). The ledger keeps a cleared episode until somebody acknowledges it and the prune window passes, so a data plane with a long history of unanswered readings has an unbounded number of them and a whole-history response would grow with it.
page_tokennoOpaque cursor from a previous response's next_page_token.

Response fields:

FieldRequiredDescription
differencesnoThe open, unacknowledged differences by default, newest first.
next_page_tokennoCursor for the next page; empty when there are no more results.
{"signatures":{"go":"func (x *AdminClient) ListDataplaneConfigDifferences(ctx context.Context, req *adminv1.ListDataplaneConfigDifferencesRequest) (*adminv1.ListDataplaneConfigDifferencesResponse, error)","python":"list_dataplane_config_differences(req: admin_pb2.ListDataplaneConfigDifferencesRequest) -\u003e ListDataplaneConfigDifferencesResponse","typescript":"listDataplaneConfigDifferences(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListDataplaneConfigDifferencesRequestSchema\u003e): Promise\u003cListDataplaneConfigDifferencesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/dataplanes/01H.../config-differences\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListDataplaneConfigDifferencesRequest{}\n\n\tresp, err := client.Admin().ListDataplaneConfigDifferences(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/admin/listdataplaneconfigdifferences\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.admin.v1 import admin_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 = admin_pb2.ListDataplaneConfigDifferencesRequest()\ntry:\n    result = client.admin.list_dataplane_config_differences(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.admin.listDataplaneConfigDifferences(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/dataplanes/01H.../config-differences\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/dataplanes/{id}/config-differences","slug":"list-dataplane-config-differences"}

List project config differences

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

What it does: List the fields the data planes serving one project disagree on.

Request fields:

FieldRequiredDescription
customer_idnoundocumented
project_idnoProject whose divergence record to read. Carries the project_id_field marker for resource-aware project_owner authz (gate amendment 5), the same as ListProjectGatewayMembers. The marker is what binds the gate to THIS field: the resolver falls back to a field conventionally named project_id, and the marker is what keeps that binding through a rename.
include_clearednoundocumented
include_acknowledgednoundocumented
page_sizenoMax differences to return per page (0 = server default). Bounded for the same reason the data plane read is: a project accumulates cleared episodes until they are acknowledged and pruned.
page_tokennoOpaque cursor from a previous response's next_page_token.

Response fields:

FieldRequiredDescription
differencesnoundocumented
next_page_tokennoCursor for the next page; empty when there are no more results.
{"signatures":{"go":"func (x *AdminClient) ListProjectConfigDifferences(ctx context.Context, req *adminv1.ListProjectConfigDifferencesRequest) (*adminv1.ListProjectConfigDifferencesResponse, error)","python":"list_project_config_differences(req: admin_pb2.ListProjectConfigDifferencesRequest) -\u003e ListProjectConfigDifferencesResponse","typescript":"listProjectConfigDifferences(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectConfigDifferencesRequestSchema\u003e): Promise\u003cListProjectConfigDifferencesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../config-differences\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectConfigDifferencesRequest{}\n\n\tresp, err := client.Admin().ListProjectConfigDifferences(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/admin/listprojectconfigdifferences\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.admin.v1 import admin_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 = admin_pb2.ListProjectConfigDifferencesRequest()\ntry:\n    result = client.admin.list_project_config_differences(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.admin.listProjectConfigDifferences(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../config-differences\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/config-differences","slug":"list-project-config-differences"}

Acknowledge config difference

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

What it does: Acknowledge one configuration difference, which takes it off the default view of the data plane or the project it reads on. The entry itself stays: nothing here deletes the record that the fleet was once split. Acknowledging an entry a second time changes nothing and reports acknowledged: false, so the ledger keeps naming whoever actually looked. A project owner answers the entries ListProjectConfigDifferences shows them by naming their project in project_id, which is what binds the gate to it. An administrator answers either list and leaves project_id empty.

Request fields:

FieldRequiredDescription
customer_idnoundocumented
idnoThe difference to acknowledge, from either list. The acknowledgement casts it to uuid in SQL, so the same pattern every other uuid id on this service carries keeps a stale or hand-typed value an invalid_argument here rather than a cast error the handler can only report as internal.
project_idnoThe project the entry reads on, for a project owner answering their own list. Naming it is what binds the gate to that project, and the entry has to be one of that project's own: an id belonging to a data plane, or to another project, comes back NOT_FOUND rather than acknowledged. An administrator leaves this empty and answers either list. min_len stays unset for that reason: an empty value is the administrator's case rather than a malformed one.

Response fields:

FieldRequiredDescription
acknowledgednoFalse when the difference was already acknowledged, which is not an error: the first acknowledgement stands and the ledger keeps naming whoever made it. That is the only thing false means. An id naming no entry the caller may answer -- one that never existed, one already pruned, or one on a data plane or another project when the caller named a project -- comes back NOT_FOUND instead, so a console can tell "somebody answered this" from "you cannot answer this".
{"signatures":{"go":"func (x *AdminClient) AcknowledgeConfigDifference(ctx context.Context, req *adminv1.AcknowledgeConfigDifferenceRequest) (*adminv1.AcknowledgeConfigDifferenceResponse, error)","python":"acknowledge_config_difference(req: admin_pb2.AcknowledgeConfigDifferenceRequest) -\u003e AcknowledgeConfigDifferenceResponse","typescript":"acknowledgeConfigDifference(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AcknowledgeConfigDifferenceRequestSchema\u003e): Promise\u003cAcknowledgeConfigDifferenceResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../config-differences/01H...:acknowledge\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AcknowledgeConfigDifferenceRequest{}\n\n\tresp, err := client.Admin().AcknowledgeConfigDifference(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/admin/acknowledgeconfigdifference\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.admin.v1 import admin_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 = admin_pb2.AcknowledgeConfigDifferenceRequest()\ntry:\n    result = client.admin.acknowledge_config_difference(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.admin.acknowledgeConfigDifference(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../config-differences/01H...:acknowledge\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/config-differences/{id}:acknowledge","slug":"acknowledge-config-difference"}

Create project gateway

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.7.0 (behaviour changes): Once a data plane declares hostnames in its chart, these three calls accept only a hostname that data plane declared, and refuse anything else with FailedPrecondition naming the chart key. A data plane that has declared nothing keeps today's behaviour, so each one crosses over as its own chart lists a name. SetDataplaneURL no longer stamps a data plane's address onto its default gateway once that data plane declares its own hostnames; it still records the address itself, which is unchanged.

Changed in v0.7.0 (deprecations): Setting a data plane's or a project gateway's address through the admin API is deprecated. A 0.7 data plane reports its own address from global.gateway.hostnames in its serve-helm values. SetDataplaneURL, its SetWorkspaceURL alias, SetProjectGatewayURL and the url field of CreateProjectGateway and UpdateProjectGateway keep working. A data plane before 0.7 cannot declare hostnames, so these calls stay until no supported data plane predates 0.7.

Changed in v0.4.0 (security updates): Claiming a hostname that is already in use no longer exposes details about the existing configuration. The conflict message now says only that the hostname is in use, preventing a rejected claim from revealing information about another organization's resources.

What it does: Create project gateway

Request fields:

FieldRequiredDescription
customer_idnoCustomer (tenant) slug that will own the project gateway.
workspace_idnoOwning dataplane (workspace) slug that hosts this project gateway.
project_gateway_idnoCaller-chosen project gateway slug, unique within the workspace.
namenoOptional human-readable display name.
descriptionnoOptional free-text description.
urlnoOptional customer-facing URL/hostname of this project gateway's ingress endpoint. Deprecated (fraser#8586): a data plane reports its own address from global.gateway.hostnames in its serve-helm values, and the management plane mirrors it read-only. This stays working in 0.6; removal is proposed for 0.8.
labelsnoOptional user-defined key/value labels for organization/filtering.

Response fields:

FieldRequiredDescription
project_gatewaynoThe newly created project gateway.
{"signatures":{"go":"func (x *AdminClient) CreateProjectGateway(ctx context.Context, req *adminv1.CreateProjectGatewayRequest) (*adminv1.CreateProjectGatewayResponse, error)","python":"create_project_gateway(req: admin_pb2.CreateProjectGatewayRequest) -\u003e CreateProjectGatewayResponse","typescript":"createProjectGateway(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateProjectGatewayRequestSchema\u003e): Promise\u003cCreateProjectGatewayResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"project_gateway_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"url\": \"...\",\n    \"labels\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateProjectGatewayRequest{}\n\n\tresp, err := client.Admin().CreateProjectGateway(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/admin/createprojectgateway\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.admin.v1 import admin_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 = admin_pb2.CreateProjectGatewayRequest()\ntry:\n    result = client.admin.create_project_gateway(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.admin.createProjectGateway(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"project_gateway_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"url\": \"...\",\n    \"labels\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/project-gateways","slug":"create-project-gateway"}

List project gateways

Changed in v0.7.0 (new features): A project gateway can now declare the environment it serves in environment, and a gateway auth policy can name the token claim carrying a token's environment in environment_claim. Only a platform administrator can set or clear a gateway's environment, and an enabled policy with environment_claim is refused on a gateway that declares none. The gateway refuses an IdP token whose environment claim does not name the gateway's environment.

What it does: List project gateways (optionally filtered by customer, workspace, and/or attached project). Each returned gateway carries its attached project slugs in attached_project_ids, so reading gateway<->project attachments in bulk is ONE paginated request, not one ListProjectGatewayProjects call per gateway (#5591).

Request fields:

FieldRequiredDescription
customer_idnoOptional filter: only return project gateways owned by this customer slug.
workspace_idnoOptional filter: only return project gateways hosted by this workspace (dataplane).
project_idsnoOptional filter: only return project gateways that have at least one of these project slugs attached. Requires customer_id -- attachments are customer-scoped, so a bare slug filter would match across tenants. Filters on the same set attached_project_ids reports, and inherits its workspace caveat: one attachment matches every same-slug gateway the customer has, so this can return more than one gateway per project. Combined with the attached_project_ids returned on each gateway, this answers "which gateways serve these projects?" in ONE request instead of a ListProjectGateways call plus one ListProjectGatewayProjects call per gateway (#5591). Repeated fields get no CLI flag, so this filter is reachable over SDK and REST only, not tare api admin project-gateways list.
page_sizenoMax project gateways to return per page (0 = server default).
page_tokennoOpaque cursor from a previous response's next_page_token.

Response fields:

FieldRequiredDescription
project_gatewaysnoPage of matching project gateways.
next_page_tokennoCursor for the next page; empty when there are no more results.
{"signatures":{"go":"func (x *AdminClient) ListProjectGateways(ctx context.Context, req *adminv1.ListProjectGatewaysRequest) (*adminv1.ListProjectGatewaysResponse, error)","python":"list_project_gateways(req: admin_pb2.ListProjectGatewaysRequest) -\u003e ListProjectGatewaysResponse","typescript":"listProjectGateways(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectGatewaysRequestSchema\u003e): Promise\u003cListProjectGatewaysResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectGatewaysRequest{}\n\n\tresp, err := client.Admin().ListProjectGateways(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/admin/listprojectgateways\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.admin.v1 import admin_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 = admin_pb2.ListProjectGatewaysRequest()\ntry:\n    result = client.admin.list_project_gateways(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.admin.listProjectGateways(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/project-gateways","slug":"list-project-gateways"}

Get project gateway

Changed in v0.7.0 (new features): A project gateway can now declare the environment it serves in environment, and a gateway auth policy can name the token claim carrying a token's environment in environment_claim. Only a platform administrator can set or clear a gateway's environment, and an enabled policy with environment_claim is refused on a gateway that declares none. The gateway refuses an IdP token whose environment claim does not name the gateway's environment.

What it does: Get project gateway

Request fields:

FieldRequiredDescription
idnoProject gateway UUID (the internal id, not the customer-chosen project_gateway_id).
project_idnoOwner scope (#4637): when the caller is a project owner (not a platform admin), this is the project they own, and the handler verifies the gateway serves it. Ignored for admins. A project owner who omits this field is refused.

Response fields:

FieldRequiredDescription
project_gatewaynoThe requested project gateway.
{"signatures":{"go":"func (x *AdminClient) GetProjectGateway(ctx context.Context, req *adminv1.GetProjectGatewayRequest) (*adminv1.GetProjectGatewayResponse, error)","python":"get_project_gateway(req: admin_pb2.GetProjectGatewayRequest) -\u003e GetProjectGatewayResponse","typescript":"getProjectGateway(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetProjectGatewayRequestSchema\u003e): Promise\u003cGetProjectGatewayResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetProjectGatewayRequest{}\n\n\tresp, err := client.Admin().GetProjectGateway(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/admin/getprojectgateway\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.admin.v1 import admin_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 = admin_pb2.GetProjectGatewayRequest()\ntry:\n    result = client.admin.get_project_gateway(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.admin.getProjectGateway(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/project-gateways/{id}","slug":"get-project-gateway"}

Update project gateway

Changed in v0.7.0 (behaviour changes): Once a data plane declares hostnames in its chart, these three calls accept only a hostname that data plane declared, and refuse anything else with FailedPrecondition naming the chart key. A data plane that has declared nothing keeps today's behaviour, so each one crosses over as its own chart lists a name. SetDataplaneURL no longer stamps a data plane's address onto its default gateway once that data plane declares its own hostnames; it still records the address itself, which is unchanged.

Changed in v0.7.0 (new features): A project gateway can now declare the environment it serves in environment, and a gateway auth policy can name the token claim carrying a token's environment in environment_claim. Only a platform administrator can set or clear a gateway's environment, and an enabled policy with environment_claim is refused on a gateway that declares none. The gateway refuses an IdP token whose environment claim does not name the gateway's environment.

Changed in v0.7.0 (deprecations): Setting a data plane's or a project gateway's address through the admin API is deprecated. A 0.7 data plane reports its own address from global.gateway.hostnames in its serve-helm values. SetDataplaneURL, its SetWorkspaceURL alias, SetProjectGatewayURL and the url field of CreateProjectGateway and UpdateProjectGateway keep working. A data plane before 0.7 cannot declare hostnames, so these calls stay until no supported data plane predates 0.7.

Changed in v0.4.0 (security updates): Claiming a hostname that is already in use no longer exposes details about the existing configuration. The conflict message now says only that the hostname is in use, preventing a rejected claim from revealing information about another organization's resources.

What it does: Update project gateway

Request fields:

FieldRequiredDescription
idnoProject gateway UUID to update.
namenoNew display name; unset leaves the existing value.
descriptionnoNew description; unset leaves the existing value.
urlnoNew customer-facing URL/hostname; unset leaves the existing value. Deprecated (fraser#8586): a data plane reports its own address from global.gateway.hostnames in its serve-helm values, and the management plane mirrors it read-only. This stays working in 0.6; removal is proposed for 0.8.
labelsnoReplacement set of labels.
project_idnoOwner scope (#4637): when the caller is a project owner (not a platform admin), this is the project they own; the handler verifies the gateway serves it. Ignored for admins.
environmentnoThe environment this gateway serves, against which the data plane compares a gateway auth policy's environment_claim (fraser#9288). The data plane refuses an IdP token whose claim does not name this environment, and refuses every token under a policy with environment_claim while the gateway declares none. Unset leaves the existing value, and an empty string clears it. A value is 1 to 63 characters, starts with a letter or digit, and holds only letters, digits, '.', '_' and '-', and it is stored exactly as written. Only a platform admin may set or clear it, and a project owner's request carrying the field is refused with PERMISSION_DENIED. That is because a gateway can serve several projects, and one project's owner would otherwise choose the environment every other project's tokens are checked against. Clearing it is refused with FAILED_PRECONDITION while an enabled gateway auth policy naming this gateway's slug sets environment_claim.

Response fields:

FieldRequiredDescription
project_gatewaynoThe updated project gateway.
warningsnoNon-fatal advisories surfaced when the update changes the gateway URL -- identical in meaning to SetProjectGatewayURLResponse.warnings (e.g. URL set but no project attached / no assigned models, so the gateway 404s until fixed). Empty when no URL was changed or the gateway is fully functional.
{"signatures":{"go":"func (x *AdminClient) UpdateProjectGateway(ctx context.Context, req *adminv1.UpdateProjectGatewayRequest) (*adminv1.UpdateProjectGatewayResponse, error)","python":"update_project_gateway(req: admin_pb2.UpdateProjectGatewayRequest) -\u003e UpdateProjectGatewayResponse","typescript":"updateProjectGateway(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateProjectGatewayRequestSchema\u003e): Promise\u003cUpdateProjectGatewayResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"url\": \"...\",\n    \"labels\": {},\n    \"project_id\": \"...\",\n    \"environment\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateProjectGatewayRequest{}\n\n\tresp, err := client.Admin().UpdateProjectGateway(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/admin/updateprojectgateway\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.admin.v1 import admin_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 = admin_pb2.UpdateProjectGatewayRequest()\ntry:\n    result = client.admin.update_project_gateway(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.admin.updateProjectGateway(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"url\": \"...\",\n    \"labels\": {},\n    \"project_id\": \"...\",\n    \"environment\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"PATCH","httpPath":"/admin/v1/project-gateways/{id}","slug":"update-project-gateway"}

Delete project gateway

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.7.0 (deprecations): A project owner attaching a project to a gateway, detaching one or deleting a gateway is deprecated, and 0.9.0 requires a platform administrator for all three. Until then a project owner can make these changes while the gateway serves only projects they own. Once a gateway serves another owner's project, only a platform administrator can change it, and a project-owner credential answers 403.

What it does: Delete project gateway (soft delete)

Request fields:

FieldRequiredDescription
idnoProject gateway UUID to soft-delete.
project_idnoOwner scope (#4637): when the caller is a project owner (not a platform admin), this is the project they own; the handler verifies the gateway serves it. Ignored for admins.

Response fields:

FieldRequiredDescription
successnoTrue if the project gateway was deleted.
deleted_atnoWhen the soft delete took effect.
{"signatures":{"go":"func (x *AdminClient) DeleteProjectGateway(ctx context.Context, req *adminv1.DeleteProjectGatewayRequest) (*adminv1.DeleteProjectGatewayResponse, error)","python":"delete_project_gateway(req: admin_pb2.DeleteProjectGatewayRequest) -\u003e DeleteProjectGatewayResponse","typescript":"deleteProjectGateway(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteProjectGatewayRequestSchema\u003e): Promise\u003cDeleteProjectGatewayResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteProjectGatewayRequest{}\n\n\tresp, err := client.Admin().DeleteProjectGateway(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/admin/deleteprojectgateway\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.admin.v1 import admin_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 = admin_pb2.DeleteProjectGatewayRequest()\ntry:\n    result = client.admin.delete_project_gateway(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.admin.deleteProjectGateway(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"DELETE","httpPath":"/admin/v1/project-gateways/{id}","slug":"delete-project-gateway"}

Attach project gateway project

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.10.0 (behaviour changes): Writing a project's OIDC contract is refused on Agent Router Service (SaaS). Enabling a contract is refused while a data plane serving the project runs a build older than 0.10.0 or has not reported its build, and so is attaching a project whose contract is enabled to such a data plane. Each refusal names the data plane.

Changed in v0.9.0 (bug fixes): These changes are now audited: data plane changes made through the workspace API, guardrail pattern and fallback-policy changes, refused gateway attaches, data plane upgrade outcomes, and the data plane URL, token revocations and MCP catalog entries a data plane writes.

Changed in v0.9.0 (bug fixes): The warning for a gateway with no URL no longer says the gateway serves nothing. It now says the gateway serves through the catch-all while it is the only gateway on its data plane, and stops serving once another gateway joins.

Changed in v0.7.0 (behaviour changes): A project gateway now holds several projects. Attaching a second, different project used to be rejected with FailedPrecondition and a "detach the current project first" message; it now succeeds wherever the data plane can enforce the per-project boundary, so one hostname serves every project attached to its gateway and each request resolves to its own project by its own credential. Two concurrent attaches of the same project leave one of them with ABORTED, which the caller retries.

Changed in v0.7.0 (deprecations): A project owner attaching a project to a gateway, detaching one or deleting a gateway is deprecated, and 0.9.0 requires a platform administrator for all three. Until then a project owner can make these changes while the gateway serves only projects they own. Once a gateway serves another owner's project, only a platform administrator can change it, and a project-owner credential answers 403.

What it does: Attach a project to a project gateway (idempotent). Establishes a gateway<->project binding in the many-to-many project_gateway_projects relationship. A project gateway holds every project attached to it, so one hostname serves several projects and each request resolves to its own project by its own credential (fraser#9422). Re-attaching the same project is a no-op. Two concurrent attaches of the same binding leave one of them with ABORTED, which the caller retries. Ensure the attached project has assigned models BEFORE setting the gateway's URL: under strict isolation a gateway with no assigned models serves an EMPTY route map and will return 404 for every request. The response carries any such warnings in the warnings field. Multi-gateway projects (fraser#5987): a project may be attached to multiple gateways, capped per project (PROJECT_GATEWAY_CAP, default 10 on Enterprise; 1 on SaaS) — attaching beyond the cap is rejected with RESOURCE_EXHAUSTED (the cap is a quota, not a name collision; ALREADY_EXISTS stays reserved for hostname/slug uniqueness conflicts). The cap is a SOFT limit: the check is not atomic with the insert, so two concurrent attaches can both pass it and overshoot the cap by one. Attaching a gateway whose slug is shared with another live gateway is rejected with FAILED_PRECONDITION (rename or delete the sibling first). A successful attach starts the membership in the syncing state; see ListProjectGatewayMembers for the state machine.

Request fields:

FieldRequiredDescription
idnoProject gateway UUID to attach the project to.
project_idnoProject slug to bind to the project gateway. The project_id_field marker names the project this request targets, which is what confines a project-scoped management key to its own project: AuthorizeAPIKeyBoundary reads the marked field on every API-key credential short of platform admin, whatever scopes the RPC declares. The project_owner check reads it too, and the handler then checks every other project the gateway serves (#8590).

Response fields:

FieldRequiredDescription
project_gatewaynoThe project gateway the project was attached to.
warningsnoNon-fatal advisories about the attachment. Populated, for example, when the attached project has no assigned models -- the gateway will serve an empty route map (404s) until models are assigned. Empty when the attachment is fully functional.
{"signatures":{"go":"func (x *AdminClient) AttachProjectGatewayProject(ctx context.Context, req *adminv1.AttachProjectGatewayProjectRequest) (*adminv1.AttachProjectGatewayProjectResponse, error)","python":"attach_project_gateway_project(req: admin_pb2.AttachProjectGatewayProjectRequest) -\u003e AttachProjectGatewayProjectResponse","typescript":"attachProjectGatewayProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AttachProjectGatewayProjectRequestSchema\u003e): Promise\u003cAttachProjectGatewayProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AttachProjectGatewayProjectRequest{}\n\n\tresp, err := client.Admin().AttachProjectGatewayProject(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/admin/attachprojectgatewayproject\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.admin.v1 import admin_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 = admin_pb2.AttachProjectGatewayProjectRequest()\ntry:\n    result = client.admin.attach_project_gateway_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.admin.attachProjectGatewayProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/project-gateways/{id}/projects","slug":"attach-project-gateway-project"}

Detach project gateway project

Changed in v0.7.0 (behaviour changes): Deleting a data plane now refuses while it is the only one serving a project, and the refusal names up to ten of those projects and reports how many there are in all. A data plane whose projects are all served by another one is deleted as before. Detaching a project from its last data plane is still allowed and now writes a PROJECT_SERVED_NOWHERE audit entry naming the project and that data plane, so the audit log carries a new action type from this release on.

Changed in v0.7.0 (bug fixes): Removing the last project from a data plane that has a single gateway now takes the project's label off, reports served_nowhere and records PROJECT_SERVED_NOWHERE in the audit log. Before, the call answered removed=true while the label stayed on the data plane, and neither was recorded.

Changed in v0.7.0 (deprecations): A project owner attaching a project to a gateway, detaching one or deleting a gateway is deprecated, and 0.9.0 requires a platform administrator for all three. Until then a project owner can make these changes while the gateway serves only projects they own. Once a gateway serves another owner's project, only a platform administrator can change it, and a project-owner credential answers 403.

What it does: Detach a project from a project gateway. Detach pushes a final zeroized config revision to the member (best-effort, DP-initiated polling) and revokes MP-side access as the authoritative backstop, so the membership lands in detached_unreachable until the data plane acknowledges the zero revision (then detached_zeroized). Detaching a project that is not attached is an idempotent no-op (success=false, no error). See ListProjectGatewayMembers for the state machine.

Request fields:

FieldRequiredDescription
idnoProject gateway UUID to detach the project from.
project_idnoProject slug to unbind from the project gateway. The project_id_field marker names the project this request targets, which is what confines a project-scoped management key to its own project: AuthorizeAPIKeyBoundary reads the marked field on every API-key credential short of platform admin, whatever scopes the RPC declares. The project_owner check reads it too, and the handler then checks every other project the gateway serves (#8590).

Response fields:

FieldRequiredDescription
successnoTrue if the binding was removed.
{"signatures":{"go":"func (x *AdminClient) DetachProjectGatewayProject(ctx context.Context, req *adminv1.DetachProjectGatewayProjectRequest) (*adminv1.DetachProjectGatewayProjectResponse, error)","python":"detach_project_gateway_project(req: admin_pb2.DetachProjectGatewayProjectRequest) -\u003e DetachProjectGatewayProjectResponse","typescript":"detachProjectGatewayProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DetachProjectGatewayProjectRequestSchema\u003e): Promise\u003cDetachProjectGatewayProjectResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DetachProjectGatewayProjectRequest{}\n\n\tresp, err := client.Admin().DetachProjectGatewayProject(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/admin/detachprojectgatewayproject\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.admin.v1 import admin_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 = admin_pb2.DetachProjectGatewayProjectRequest()\ntry:\n    result = client.admin.detach_project_gateway_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.admin.detachProjectGatewayProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"DELETE","httpPath":"/admin/v1/project-gateways/{id}/projects/{project_id}","slug":"detach-project-gateway-project"}

Update project gateway project

Changed in v0.7.0 (new features): A project's membership of a project gateway now accepts ACCEPTED_CREDENTIALS_TOKEN on Enterprise, so the gateway refuses API keys for that project and accepts only IdP tokens. ACCEPTED_CREDENTIALS_BOTH no longer returns a warning. A data plane older than 0.7.0 keeps accepting API keys whatever the membership declares.

Changed in v0.6.0 (new features): Project gateway attachments now record accepted_credentials; existing attachments read API_KEY. Enterprise projects with an enabled jwt gateway auth policy can choose BOTH, which prevents disabling or deleting their last enabled policy. TOKEN is refused for now. The gateway does not yet enforce this setting: API keys still work, and an identity-provider token alone does not authenticate a caller.

What it does: Update a project's membership of a project gateway. The one mutable field is accepted_credentials, which says whether an Agent Router API key, a verified IdP token, or either one authenticates a caller of this project on this gateway (ADR 050, fraser#9834). A new attachment starts at ACCEPTED_CREDENTIALS_API_KEY, which is what every project did before the field existed. TOKEN and BOTH declare that the project accepts a credential verified at this gateway, so both are refused with FAILED_PRECONDITION while the project holds no enabled jwt gateway auth policy for this gateway, and disabling or deleting the project's last such policy is refused while the membership declares either one. Both are Enterprise-only, refused with FAILED_PRECONDITION on SaaS the way a jwt gateway auth policy is. The data plane enforces the declaration from release 0.7.0: it refuses an IdP token on a project declaring API_KEY, and an API key on a project declaring TOKEN. A data plane older than 0.7.0 authenticates API keys alone, whatever the declaration says. Returns NOT_FOUND when the project is not attached to this gateway.

Request fields:

FieldRequiredDescription
idnoProject gateway UUID the project is attached to.
project_idnoAttached project slug. Carries the project_id_field marker so resource-aware project_owner authz targets exactly this project.
accepted_credentialsnoWhich credentials authenticate a caller of this project on this gateway.

Response fields:

FieldRequiredDescription
attachmentnoThe membership as stored.
warningsnoNon-fatal advisories about the stored membership. Empty when there are none.
{"signatures":{"go":"func (x *AdminClient) UpdateProjectGatewayProject(ctx context.Context, req *adminv1.UpdateProjectGatewayProjectRequest) (*adminv1.UpdateProjectGatewayProjectResponse, error)","python":"update_project_gateway_project(req: admin_pb2.UpdateProjectGatewayProjectRequest) -\u003e UpdateProjectGatewayProjectResponse","typescript":"updateProjectGatewayProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateProjectGatewayProjectRequestSchema\u003e): Promise\u003cUpdateProjectGatewayProjectResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"accepted_credentials\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateProjectGatewayProjectRequest{}\n\n\tresp, err := client.Admin().UpdateProjectGatewayProject(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/admin/updateprojectgatewayproject\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.admin.v1 import admin_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 = admin_pb2.UpdateProjectGatewayProjectRequest()\ntry:\n    result = client.admin.update_project_gateway_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.admin.updateProjectGatewayProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"accepted_credentials\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"PATCH","httpPath":"/admin/v1/project-gateways/{id}/projects/{project_id}","slug":"update-project-gateway-project"}

List project gateway projects

Changed in v0.6.0 (new features): Project gateway attachments now record accepted_credentials; existing attachments read API_KEY. Enterprise projects with an enabled jwt gateway auth policy can choose BOTH, which prevents disabling or deleting their last enabled policy. TOKEN is refused for now. The gateway does not yet enforce this setting: API keys still work, and an identity-provider token alone does not authenticate a caller.

What it does: List the project slugs attached to a project gateway.

Request fields:

FieldRequiredDescription
idnoProject gateway UUID whose attached projects are listed.

Response fields:

FieldRequiredDescription
project_idsnoProject slugs currently attached to the project gateway.
attachmentsnoThe same attachments as project_ids, in the same order, each with the credentials the project accepts on this gateway.
{"signatures":{"go":"func (x *AdminClient) ListProjectGatewayProjects(ctx context.Context, req *adminv1.ListProjectGatewayProjectsRequest) (*adminv1.ListProjectGatewayProjectsResponse, error)","python":"list_project_gateway_projects(req: admin_pb2.ListProjectGatewayProjectsRequest) -\u003e ListProjectGatewayProjectsResponse","typescript":"listProjectGatewayProjects(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectGatewayProjectsRequestSchema\u003e): Promise\u003cListProjectGatewayProjectsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectGatewayProjectsRequest{}\n\n\tresp, err := client.Admin().ListProjectGatewayProjects(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/admin/listprojectgatewayprojects\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.admin.v1 import admin_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 = admin_pb2.ListProjectGatewayProjectsRequest()\ntry:\n    result = client.admin.list_project_gateway_projects(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.admin.listProjectGatewayProjects(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways/01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/project-gateways/{id}/projects","slug":"list-project-gateway-projects"}

List project gateway members

Changed in v0.7.0 (new features): A data plane now reports each whitelisted field on which it serves something other than the bundle the management plane sent, with both values, and a project reports the fields its data planes disagree on. The management plane labels each difference as an intended override, as a data plane that has not pulled yet, or as one nothing explains. An administrator or the project's owner acknowledges a difference, and one that clears stays on record until then.

Changed in v0.7.0 (new features): A project's gateway members now come back with where the project stands across the data planes serving it: the revision last minted for its configuration, how many labelled data planes have confirmed that revision, and how many carry the label at all. A member is one ingress endpoint and one data plane hosts several of them, so the two readings answer different questions and the rollup is the one that says whether the project is covered.

Changed in v0.6.0 (new features): Project gateway attachments now record accepted_credentials; existing attachments read API_KEY. Enterprise projects with an enabled jwt gateway auth policy can choose BOTH, which prevents disabling or deleting their last enabled policy. TOKEN is refused for now. The gateway does not yet enforce this setting: API keys still work, and an identity-provider token alone does not authenticate a caller.

What it does: List a project's member gateways with their membership state (D1 multi-gateway projects, fraser#5987 / ADR 052). This is the fleet-consistency primitive (epic tetrate-ai-platform#2865, gate amendment 6): for every member it reports the membership state machine position (syncing / ready / detached_zeroized / detached_unreachable), the member's last-acked config version vs. the project's head config version for that member, health (tri-state: unknown is a valid answer), last-seen, and the state timestamps. The shape is deliberately reusable by future consumers (D3 T1 steering, fleet-upgrade tooling): "is this fleet converged on config head?" is answerable per member from status + config_version + head_config_version alone. A member is advertised as ready ONLY under confirmed convergence: every per-gateway config slot acked by the data plane at its current version, PLUS the member workspace's shared PROXY (authz-map) slot when one exists (an absent workspace slot passes vacuously — the slot is minted on first authz-map generation). Because that PROXY slot is shared by every gateway in the workspace, a bump to it flips ALL of the workspace's members back to syncing until the new map version is acked — cross-member flap on workspace-slot bumps is expected behavior, not a defect. A previously-ready member whose project config moved ahead reports syncing again until the new head is acked. The config_version / head_config_version columns stay scoped to the member's own per-gateway slots (gateway family only): the workspace PROXY slot participates in the READY predicate but never in the version columns. Although marked NO_SIDE_EFFECTS, this read performs idempotent ledger reconciliation: attachments that predate the membership ledger are backfilled insert-only (a detached record is never reset by a list; only the Attach RPC does that). A legacy attachment backfilled this way gets a fabricated attached_at equal to the first list's server time — its true attach time was never recorded. A project with ZERO member gateways is fully valid: the response carries an empty members list (and whatever detached history exists), never an error. Responses carry NO credential material (gate amendment 5): identity, state, versions, and timestamps only. Enterprise only: on SaaS deployments (DEPLOYMENT_PRODUCT=saas) this RPC fails with UNIMPLEMENTED — the multi-gateway surface does not exist there (the existing attach/detach RPCs remain, capped at one gateway per project).

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose member gateways to list. Carries the project_id_field marker for resource-aware project_owner authz (gate amendment 5).

Response fields:

FieldRequiredDescription
membersnoLive member gateways (attached; state SYNCING or READY). Empty for a zero-gateway project — a fully valid state, not an error.
recently_detachednoDetached membership records (state DETACHED_ZEROIZED or DETACHED_UNREACHABLE), most recently detached first, so operators can verify teardown after the member leaves the live list. Bounded: at most the 20 most recently detached records are returned; older history is retained in storage but not listed.
gateway_capnoEffective per-project gateway cap for this deployment (PROJECT_GATEWAY_CAP, default 10 on Enterprise; 1 on SaaS). Attaching beyond it fails with RESOURCE_EXHAUSTED. The cap is a soft limit: the check is not atomic with the attach, so concurrent attaches can overshoot it by one.
servingnoWhere the project stands across the DATA PLANES serving it, which the members list above cannot answer: a member is an ingress endpoint, and one data plane hosts many of them. Unset on a deployment whose readings are not available.
diverging_field_countnoHow many whitelisted fields this project's data planes disagree on, which is the "data planes disagree (1 field)" badge on the project (tetrateio/fraser#8588). Zero when they hold the same configuration. An acknowledged difference still counts. Answering one does not make the data planes agree, and acknowledging an intended override is the commonest answer there is, so dropping it here would let this receipt report convergence for a project whose data planes call different provider addresses.
differencesnoThe differing fields with what explains each, acknowledged ones included for the same reason. A member list reporting convergence alone reads two data planes as identical while their effective configuration differs, so an intended difference is named here rather than suppressed. ListProjectConfigDifferences carries the values behind it.
{"signatures":{"go":"func (x *AdminClient) ListProjectGatewayMembers(ctx context.Context, req *adminv1.ListProjectGatewayMembersRequest) (*adminv1.ListProjectGatewayMembersResponse, error)","python":"list_project_gateway_members(req: admin_pb2.ListProjectGatewayMembersRequest) -\u003e ListProjectGatewayMembersResponse","typescript":"listProjectGatewayMembers(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectGatewayMembersRequestSchema\u003e): Promise\u003cListProjectGatewayMembersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../gateway-members\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectGatewayMembersRequest{}\n\n\tresp, err := client.Admin().ListProjectGatewayMembers(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/admin/listprojectgatewaymembers\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.admin.v1 import admin_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 = admin_pb2.ListProjectGatewayMembersRequest()\ntry:\n    result = client.admin.list_project_gateway_members(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.admin.listProjectGatewayMembers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../gateway-members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/gateway-members","slug":"list-project-gateway-members"}

Set project gateway URL

Changed in v0.7.0 (behaviour changes): Once a data plane declares hostnames in its chart, these three calls accept only a hostname that data plane declared, and refuse anything else with FailedPrecondition naming the chart key. A data plane that has declared nothing keeps today's behaviour, so each one crosses over as its own chart lists a name. SetDataplaneURL no longer stamps a data plane's address onto its default gateway once that data plane declares its own hostnames; it still records the address itself, which is unchanged.

Changed in v0.7.0 (deprecations): Setting a data plane's or a project gateway's address through the admin API is deprecated. A 0.7 data plane reports its own address from global.gateway.hostnames in its serve-helm values. SetDataplaneURL, its SetWorkspaceURL alias, SetProjectGatewayURL and the url field of CreateProjectGateway and UpdateProjectGateway keep working. A data plane before 0.7 cannot declare hostnames, so these calls stay until no supported data plane predates 0.7.

Changed in v0.4.0 (security updates): Claiming a hostname that is already in use no longer exposes details about the existing configuration. The conflict message now says only that the hostname is in use, preventing a rejected claim from revealing information about another organization's resources.

Deprecated

What it does: Set the customer-facing URL/hostname for a project gateway. The hostname (host part of the URL) must be globally UNIQUE across all project gateways in the platform; setting a hostname already bound to a different gateway is rejected with ALREADY_EXISTS. Behavior change (strict isolation): once any gateway in a data plane's workspace has its URL set, that data plane serves ONLY per-gateway host-scoped routes -- the default all-models route is suppressed, so clients must call the gateway hostname rather than the workspace's shared URL. Best practice: attach a project and assign its models BEFORE setting the URL. Setting a URL on a gateway with no attached project (or whose project has no assigned models) makes the gateway reachable but it will return 404 for every request until a project with assigned models is attached. The response surfaces any such condition in the warnings field. Deprecated (fraser#8586): a data plane reports its own address from global.gateway.hostnames in its serve-helm values, and the management plane mirrors it read-only. This stays working in 0.6; removal is proposed for 0.8.

Request fields:

FieldRequiredDescription
idnoProject gateway UUID whose URL is being set.
urlnourl is the customer-facing URL/hostname of the project gateway's ingress endpoint. Its host part must be globally unique across all project gateways (a hostname bound to another gateway is rejected with ALREADY_EXISTS).
project_idnoOwner scope (#4637): when the caller is a project owner (not a platform admin), this is the project they own; the handler verifies the gateway serves it. Ignored for admins.

Response fields:

FieldRequiredDescription
project_gatewaynoThe project gateway reflecting the new URL.
warningsnoNon-fatal advisories about the URL change. Populated, for example, when the gateway has no attached project (or its project has no assigned models) -- the gateway is now reachable but will return 404 for every request until a project with assigned models is attached. Empty when the gateway is fully functional.
{"signatures":{"go":"func (x *AdminClient) SetProjectGatewayURL(ctx context.Context, req *adminv1.SetProjectGatewayURLRequest) (*adminv1.SetProjectGatewayURLResponse, error)","python":"set_project_gateway_url(req: admin_pb2.SetProjectGatewayURLRequest) -\u003e SetProjectGatewayURLResponse","typescript":"setProjectGatewayURL(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetProjectGatewayURLRequestSchema\u003e): Promise\u003cSetProjectGatewayURLResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetProjectGatewayURLRequest{}\n\n\tresp, err := client.Admin().SetProjectGatewayURL(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/admin/setprojectgatewayurl\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.admin.v1 import admin_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 = admin_pb2.SetProjectGatewayURLRequest()\ntry:\n    result = client.admin.set_project_gateway_url(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.admin.setProjectGatewayURL(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways/01H.../url\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"...\",\n    \"project_id\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/project-gateways/{id}/url","slug":"set-project-gateway-url"}

Set project gateway workspace

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.9.0 (bug fixes): The warning for a gateway with no URL no longer says the gateway serves nothing. It now says the gateway serves through the catch-all while it is the only gateway on its data plane, and stops serving once another gateway joins.

What it does: Reassign a project gateway to a different dataplane (workspace). A data plane serves ONLY the hostnames of project gateways whose workspace_id matches its own (via per-gateway host-scoped routes plus the P10 authz map). Moving a gateway is therefore NOT a bare DB flip: this RPC tears down the gateway's per-gateway routes + authz binding on the OLD data plane and materializes them on the NEW one, refreshing both workspaces' authz maps and default-route suppression. The gateway's hostname is unchanged, so DNS is NOT moved automatically: the hostname still resolves to the OLD data plane's ingress until an operator repoints it. Until that cutover, requests to the hostname hit the old data plane (now torn down) and 404. The response ALWAYS includes a warnings entry reminding the operator to repoint DNS (and provision the new data plane's TLS cert). Recommended order: provision the new data plane's DNS/cert, call this RPC, then cut DNS over. Reassigning to the gateway's current workspace is a no-op. The new workspace must exist for the gateway's customer, and the gateway's slug must be free in the new workspace (a collision is rejected with ALREADY_EXISTS).

Request fields:

FieldRequiredDescription
idnoProject gateway UUID to reassign.
workspace_idnoTarget dataplane (workspace) slug to move the project gateway to. Must exist for the gateway's customer, and the gateway's slug must be free in it.

Response fields:

FieldRequiredDescription
project_gatewaynoThe project gateway reflecting the new workspace.
warningsnoNon-fatal advisories about the move. ALWAYS includes a reminder that the gateway's hostname is unchanged and must be repointed (DNS + TLS cert) to the new dataplane's ingress, or traffic will 404 on the old dataplane until cutover. May also carry the same no-project / no-models / no-URL advisories as SetProjectGatewayURL when the gateway is not yet fully functional.
{"signatures":{"go":"func (x *AdminClient) SetProjectGatewayWorkspace(ctx context.Context, req *adminv1.SetProjectGatewayWorkspaceRequest) (*adminv1.SetProjectGatewayWorkspaceResponse, error)","python":"set_project_gateway_workspace(req: admin_pb2.SetProjectGatewayWorkspaceRequest) -\u003e SetProjectGatewayWorkspaceResponse","typescript":"setProjectGatewayWorkspace(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.SetProjectGatewayWorkspaceRequestSchema\u003e): Promise\u003cSetProjectGatewayWorkspaceResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/project-gateways/01H.../workspace\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"workspace_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.SetProjectGatewayWorkspaceRequest{}\n\n\tresp, err := client.Admin().SetProjectGatewayWorkspace(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/admin/setprojectgatewayworkspace\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.admin.v1 import admin_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 = admin_pb2.SetProjectGatewayWorkspaceRequest()\ntry:\n    result = client.admin.set_project_gateway_workspace(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.admin.setProjectGatewayWorkspace(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/project-gateways/01H.../workspace\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"workspace_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/project-gateways/{id}/workspace","slug":"set-project-gateway-workspace"}

Create service account

Changed in v0.8.0 (security updates): SetWorkspaceURL and SetDataplaneURL refuse to set or clear a data plane URL with FailedPrecondition when another organization uses the same data plane ID. The URL was stored under the ID alone, so the write also changed the other organization's data plane. CreateServiceAccount with a serve URL for such an ID is refused too when no URL is stored for that ID yet. The Admin Console's System Settings save does not check this yet; it moves onto SetDataplaneURL in a later release.

Changed in v0.1.5 (bug fixes): Creating or revoking a service account now takes effect in seconds rather than minutes. The published key set is refreshed immediately by the instance handling the change and within 30 seconds elsewhere, where previously either could take up to five minutes, long enough that a new service account was rejected as if its credentials were wrong, and a revoked one kept being accepted.

What it does: Create service account

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug the service account belongs to.
workspace_idnoWorkspace slug the service account is scoped to.
validity_daysnoHow many days the generated credential stays valid (default applied if unset).
api_urinoManagement-plane API base URI embedded in the service account.
serve_urlnoCustomer-facing data-plane serve URL embedded in the service account.
issuernoJWT issuer (iss) to embed in the auth-server config.
audiencenoJWT audience (aud) to embed in the auth-server config.
jwks_urinoJWKS endpoint URI for verifying tokens issued to this account.
telemetry_endpointnoOTLP exporter endpoint for telemetry export.
telemetry_protocolnoOTLP wire protocol: grpc, http/protobuf, or http/json.
telemetry_insecurenoIf true, skip TLS verification for the telemetry endpoint.
telemetry_timeoutnoOTLP export timeout as a Go duration (e.g. "10s").
telemetry_headersnoExtra headers attached to telemetry exports (e.g. auth tokens).
scopesnoOAuth-style scopes granted to the service account.
router_urlnoOptional: Router configuration to include in generated service account. When providing router_key this may be either a plaintext key (the server will store it in the configured secret manager and replace with a secret ref) or a secret reference (e.g. noop://..., sm://..., arn:aws:...).
router_keynoundocumented
internal_api_keynoOptional: Internal API key for dataplane → management plane authentication. In production (DB mode): Must be a secret reference (e.g., projects/.../secrets/internal-api-key-...). Generated offline via admin CLI and stored in remote Secret Manager (GCP/AWS). In file mode: Can be plaintext for local development. Typically per-customer (one key shared by all service accounts for the customer).
telemetry_local_varsnoOptional: Local OTEL environment variable overrides to embed in the service account. Values may be plaintext or secret references (e.g., sm://project/secret, noop://name). The server resolves any secret references via the configured secret manager and re-stores them as valet:// references before embedding in the generated service account. The dataplane resolves valet:// references at load time so initLocalDestination sees plaintext values when constructing the OTEL exporter. Example: {"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer sm://myproject/otlp-token"}
rolesnoOptional: built-in role slugs to bind this service account to at creation (fraser#5714). Each becomes an org-scoped rbac_binding on the SA principal, so the SA's calls resolve through RBAC — e.g. "internal" for a data-plane worker, whose control-loop callbacks then no longer need the coarse admin scope. Unknown or not-yet-seeded roles are skipped; binding is best-effort and never fails service-account creation.

Response fields:

FieldRequiredDescription
service_accountnoThe generated service account, including the private key (returned only here).
checksumnoIntegrity checksum over the canonical service-account JSON.
checksum_algorithmnoHash algorithm used for checksum (e.g. "sha256").
{"signatures":{"go":"func (x *AdminClient) CreateServiceAccount(ctx context.Context, req *adminv1.CreateServiceAccountRequest) (*adminv1.CreateServiceAccountResponse, error)","python":"create_service_account(req: admin_pb2.CreateServiceAccountRequest) -\u003e CreateServiceAccountResponse","typescript":"createServiceAccount(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateServiceAccountRequestSchema\u003e): Promise\u003cCreateServiceAccountResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/service-accounts\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"validity_days\": 0,\n    \"api_uri\": \"...\",\n    \"serve_url\": \"...\",\n    \"issuer\": \"...\",\n    \"audience\": \"...\",\n    \"jwks_uri\": \"...\",\n    \"telemetry_endpoint\": \"...\",\n    \"telemetry_protocol\": \"...\",\n    \"telemetry_insecure\": false,\n    \"telemetry_timeout\": \"...\",\n    \"telemetry_headers\": {},\n    \"scopes\": [],\n    \"router_url\": \"...\",\n    \"router_key\": \"...\",\n    \"internal_api_key\": \"...\",\n    \"telemetry_local_vars\": {},\n    \"roles\": []\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateServiceAccountRequest{}\n\n\tresp, err := client.Admin().CreateServiceAccount(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/admin/createserviceaccount\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.admin.v1 import admin_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 = admin_pb2.CreateServiceAccountRequest()\ntry:\n    result = client.admin.create_service_account(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.admin.createServiceAccount(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/service-accounts\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"validity_days\": 0,\n    \"api_uri\": \"...\",\n    \"serve_url\": \"...\",\n    \"issuer\": \"...\",\n    \"audience\": \"...\",\n    \"jwks_uri\": \"...\",\n    \"telemetry_endpoint\": \"...\",\n    \"telemetry_protocol\": \"...\",\n    \"telemetry_insecure\": false,\n    \"telemetry_timeout\": \"...\",\n    \"telemetry_headers\": {},\n    \"scopes\": [],\n    \"router_url\": \"...\",\n    \"router_key\": \"...\",\n    \"internal_api_key\": \"...\",\n    \"telemetry_local_vars\": {},\n    \"roles\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/service-accounts","slug":"create-service-account"}

List service accounts

What it does: List service accounts

Request fields:

FieldRequiredDescription
customer_idnoOptional filter by owning customer slug.
workspace_idnoOptional filter by workspace slug.
statusnoOptional filter by account status.
page_sizenoMax results per page (0 = server default).
page_tokennoOpaque pagination cursor from a prior response.

Response fields:

FieldRequiredDescription
service_accountsnoPage of service account summaries (no private keys).
next_page_tokennoCursor for the next page; empty when exhausted.
{"signatures":{"go":"func (x *AdminClient) ListServiceAccounts(ctx context.Context, req *adminv1.ListServiceAccountsRequest) (*adminv1.ListServiceAccountsResponse, error)","python":"list_service_accounts(req: admin_pb2.ListServiceAccountsRequest) -\u003e ListServiceAccountsResponse","typescript":"listServiceAccounts(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListServiceAccountsRequestSchema\u003e): Promise\u003cListServiceAccountsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/service-accounts\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListServiceAccountsRequest{}\n\n\tresp, err := client.Admin().ListServiceAccounts(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/admin/listserviceaccounts\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.admin.v1 import admin_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 = admin_pb2.ListServiceAccountsRequest()\ntry:\n    result = client.admin.list_service_accounts(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.admin.listServiceAccounts(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/service-accounts\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/service-accounts","slug":"list-service-accounts"}

Get service account

What it does: Get service account

Request fields:

FieldRequiredDescription
idnoService account UUID to fetch.

Response fields:

FieldRequiredDescription
service_accountnoThe requested service account summary.
{"signatures":{"go":"func (x *AdminClient) GetServiceAccount(ctx context.Context, req *adminv1.GetServiceAccountRequest) (*adminv1.GetServiceAccountResponse, error)","python":"get_service_account(req: admin_pb2.GetServiceAccountRequest) -\u003e GetServiceAccountResponse","typescript":"getServiceAccount(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetServiceAccountRequestSchema\u003e): Promise\u003cGetServiceAccountResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/service-accounts/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetServiceAccountRequest{}\n\n\tresp, err := client.Admin().GetServiceAccount(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/admin/getserviceaccount\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.admin.v1 import admin_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 = admin_pb2.GetServiceAccountRequest()\ntry:\n    result = client.admin.get_service_account(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.admin.getServiceAccount(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/service-accounts/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/service-accounts/{id}","slug":"get-service-account"}

Revoke service account

Changed in v0.1.5 (bug fixes): Creating or revoking a service account now takes effect in seconds rather than minutes. The published key set is refreshed immediately by the instance handling the change and within 30 seconds elsewhere, where previously either could take up to five minutes, long enough that a new service account was rejected as if its credentials were wrong, and a revoked one kept being accepted.

What it does: Revoke service account

Request fields:

FieldRequiredDescription
idnoService account UUID to revoke.
reasonnoOptional human-readable revocation reason (audit trail).

Response fields:

FieldRequiredDescription
successnoTrue if the account was revoked.
revoked_atnoWhen the revocation took effect.
{"signatures":{"go":"func (x *AdminClient) RevokeServiceAccount(ctx context.Context, req *adminv1.RevokeServiceAccountRequest) (*adminv1.RevokeServiceAccountResponse, error)","python":"revoke_service_account(req: admin_pb2.RevokeServiceAccountRequest) -\u003e RevokeServiceAccountResponse","typescript":"revokeServiceAccount(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RevokeServiceAccountRequestSchema\u003e): Promise\u003cRevokeServiceAccountResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/service-accounts/01H...:revoke\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RevokeServiceAccountRequest{}\n\n\tresp, err := client.Admin().RevokeServiceAccount(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/admin/revokeserviceaccount\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.admin.v1 import admin_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 = admin_pb2.RevokeServiceAccountRequest()\ntry:\n    result = client.admin.revoke_service_account(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.admin.revokeServiceAccount(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/service-accounts/01H...:revoke\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/service-accounts/{id}:revoke","slug":"revoke-service-account"}

Restore service account

What it does: Restore service account Restores a revoked service account to active status. Only one active service account per customer_id + workspace_id is allowed.

Request fields:

FieldRequiredDescription
idnoService account UUID to restore to active.
reasonnoOptional human-readable restore reason (audit trail).

Response fields:

FieldRequiredDescription
successnoTrue if the account was restored.
service_accountnoThe restored account summary.
{"signatures":{"go":"func (x *AdminClient) RestoreServiceAccount(ctx context.Context, req *adminv1.RestoreServiceAccountRequest) (*adminv1.RestoreServiceAccountResponse, error)","python":"restore_service_account(req: admin_pb2.RestoreServiceAccountRequest) -\u003e RestoreServiceAccountResponse","typescript":"restoreServiceAccount(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RestoreServiceAccountRequestSchema\u003e): Promise\u003cRestoreServiceAccountResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/service-accounts/01H...:restore\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RestoreServiceAccountRequest{}\n\n\tresp, err := client.Admin().RestoreServiceAccount(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/admin/restoreserviceaccount\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.admin.v1 import admin_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 = admin_pb2.RestoreServiceAccountRequest()\ntry:\n    result = client.admin.restore_service_account(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.admin.restoreServiceAccount(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/service-accounts/01H...:restore\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/service-accounts/{id}:restore","slug":"restore-service-account"}

Create user token

Changed in v0.8.0 (bug fixes): Adding or removing a model from a project now updates keys that carry their own settings (BYOK, fallback, traffic split, or a rate limit), so they no longer keep routing against the old model list. A key created with CreateApiKey or IssueMyKey now gets its own routes instead of waiting on an unrelated change. Both updates are sent in the background, so the call returns without waiting for them.

Changed in v0.4.0 (bug fixes): Creating or rotating a routing key through the API saves the key and its client membership together. If membership setup fails, no partial key or client records remain. Newly created standalone routing keys also appear in the client list; those created directly through the token API have no client title.

Changed in v0.3.0 (bug fixes): Creating an API key now schedules a budget snapshot refresh instead of waiting for the next periodic rebuild, up to five minutes by default. Exhausted budgets begin enforcing on the new key once the updated snapshot reaches the data plane. The refresh runs in the background; it does not delay key creation.

What it does: Create user token Generates a JWT token for user authentication with gatekeeper.

Request fields:

FieldRequiredDescription
customer_idnoCustomer ID (e.g., "acme", "default")
workspace_idnoWorkspace ID (e.g., "production", "staging", "internal")
user_idnoUser ID from authentication provider (opaque identifier)
rolenoUser role from authentication (e.g., "developer", "admin")
organization_unitnoOrganization unit from authentication (e.g., "engineering", "sales")
expires_in_daysnoToken lifetime in days (default applied if unset).
scopesnoOAuth-style scopes embedded in the issued token.
namenoOptional human-readable name for the token
impersonatenoIf true, the token will not be persisted to the database. This is used for impersonation scenarios where the token is temporary.
impersonation_metadatanoOptional metadata for impersonation tracking. When impersonate=true, this should contain the original user/admin who is impersonating.
project_idnoProject the key is scoped to within customer_id. Unset means the "default" project; for a non-default project the subject user must be a member (#4479). When set it is also embedded as the inference token's "project" claim so the dataplane stamps the internal x-project-id egress header without a key->project lookup (#4637).

Response fields:

FieldRequiredDescription
access_tokennoThe signed JWT to use as a bearer credential.
token_typenoToken type, typically "Bearer".
expires_innoSeconds until the token expires.
expires_atnoAbsolute expiry timestamp.
jtioutput-onlyJWT ID (jti); used to look up and revoke the token.
key_prefixnoDatabase storage identifiers (for internal use)
key_hashnoundocumented
key_addressnoundocumented
{"signatures":{"go":"func (x *AdminClient) CreateUserToken(ctx context.Context, req *adminv1.CreateUserTokenRequest) (*adminv1.CreateUserTokenResponse, error)","python":"create_user_token(req: admin_pb2.CreateUserTokenRequest) -\u003e CreateUserTokenResponse","typescript":"createUserToken(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateUserTokenRequestSchema\u003e): Promise\u003cCreateUserTokenResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/user-tokens\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"user_id\": \"...\",\n    \"role\": \"...\",\n    \"organization_unit\": \"...\",\n    \"expires_in_days\": 0,\n    \"scopes\": [],\n    \"name\": \"...\",\n    \"impersonate\": false,\n    \"impersonation_metadata\": {},\n    \"project_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateUserTokenRequest{}\n\n\tresp, err := client.Admin().CreateUserToken(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/admin/createusertoken\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.admin.v1 import admin_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 = admin_pb2.CreateUserTokenRequest()\ntry:\n    result = client.admin.create_user_token(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.admin.createUserToken(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/user-tokens\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"workspace_id\": \"...\",\n    \"user_id\": \"...\",\n    \"role\": \"...\",\n    \"organization_unit\": \"...\",\n    \"expires_in_days\": 0,\n    \"scopes\": [],\n    \"name\": \"...\",\n    \"impersonate\": false,\n    \"impersonation_metadata\": {},\n    \"project_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/user-tokens","slug":"create-user-token"}

List user tokens

Changed in v0.11.0 (behaviour changes): A disabled user token now shows the new DISABLED status, and the active filter no longer returns it. It was shown as active even though the data plane does not route it. A token that is both disabled and revoked or expired still shows REVOKED or EXPIRED. ListUserTokens takes a new disabled status filter that returns disabled tokens that are neither revoked nor expired; filter by revoked or expired to find the others.

Changed in v0.2.0 (security updates): Listing, reading and revoking user tokens through the admin API is now confined to the calling credential's own organization. A credential carrying the broad admin scope could previously act on any organization's tokens, because these operations matched a token by its id alone and never checked who was asking. Naming a different organization on the request is refused. Credentials that are not tied to an organization, such as an operator's environment-configured key, are unaffected. An organization administrator signed in to the dashboard can now list, read and revoke their own organization's tokens through these operations, which an organization-scoped API key still cannot do. Before upgrading a management plane that serves more than one organization, re-scope by hand any user tokens still stamped with the placeholder organization "default": until you do, the organization that owns them can no longer read or revoke them.

What it does: List user tokens

Request fields:

FieldRequiredDescription
user_idnoOptional filter by issuing user ID.
statusnoOptional filter by token status.
page_sizenoMax results per page (0 = server default).
page_tokennoOpaque pagination cursor from a prior response.
customer_idnoCustomer that owns the token. Optional for compatibility: a credential bound to a customer is confined to it whether or not this is set, and naming a different customer is denied.

Response fields:

FieldRequiredDescription
tokensnoPage of user token summaries.
next_page_tokennoCursor for the next page; empty when exhausted.
{"signatures":{"go":"func (x *AdminClient) ListUserTokens(ctx context.Context, req *adminv1.ListUserTokensRequest) (*adminv1.ListUserTokensResponse, error)","python":"list_user_tokens(req: admin_pb2.ListUserTokensRequest) -\u003e ListUserTokensResponse","typescript":"listUserTokens(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListUserTokensRequestSchema\u003e): Promise\u003cListUserTokensResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/user-tokens\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListUserTokensRequest{}\n\n\tresp, err := client.Admin().ListUserTokens(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/admin/listusertokens\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.admin.v1 import admin_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 = admin_pb2.ListUserTokensRequest()\ntry:\n    result = client.admin.list_user_tokens(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.admin.listUserTokens(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/user-tokens\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/user-tokens","slug":"list-user-tokens"}

Get user token

Changed in v0.11.0 (behaviour changes): A disabled user token now shows the new DISABLED status, and the active filter no longer returns it. It was shown as active even though the data plane does not route it. A token that is both disabled and revoked or expired still shows REVOKED or EXPIRED. ListUserTokens takes a new disabled status filter that returns disabled tokens that are neither revoked nor expired; filter by revoked or expired to find the others.

Changed in v0.2.0 (security updates): Listing, reading and revoking user tokens through the admin API is now confined to the calling credential's own organization. A credential carrying the broad admin scope could previously act on any organization's tokens, because these operations matched a token by its id alone and never checked who was asking. Naming a different organization on the request is refused. Credentials that are not tied to an organization, such as an operator's environment-configured key, are unaffected. An organization administrator signed in to the dashboard can now list, read and revoke their own organization's tokens through these operations, which an organization-scoped API key still cannot do. Before upgrading a management plane that serves more than one organization, re-scope by hand any user tokens still stamped with the placeholder organization "default": until you do, the organization that owns them can no longer read or revoke them.

What it does: Get user token

Request fields:

FieldRequiredDescription
jtinoJWT ID (jti) of the token to fetch.
customer_idnoCustomer that owns the token. Optional for compatibility: a credential bound to a customer is confined to it whether or not this is set, and naming a different customer is denied.

Response fields:

FieldRequiredDescription
tokennoThe requested token summary.
{"signatures":{"go":"func (x *AdminClient) GetUserToken(ctx context.Context, req *adminv1.GetUserTokenRequest) (*adminv1.GetUserTokenResponse, error)","python":"get_user_token(req: admin_pb2.GetUserTokenRequest) -\u003e GetUserTokenResponse","typescript":"getUserToken(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetUserTokenRequestSchema\u003e): Promise\u003cGetUserTokenResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/user-tokens/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetUserTokenRequest{}\n\n\tresp, err := client.Admin().GetUserToken(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/admin/getusertoken\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.admin.v1 import admin_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 = admin_pb2.GetUserTokenRequest()\ntry:\n    result = client.admin.get_user_token(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.admin.getUserToken(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/user-tokens/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/user-tokens/{jti}","slug":"get-user-token"}

Revoke user token

Changed in v0.2.0 (security updates): Listing, reading and revoking user tokens through the admin API is now confined to the calling credential's own organization. A credential carrying the broad admin scope could previously act on any organization's tokens, because these operations matched a token by its id alone and never checked who was asking. Naming a different organization on the request is refused. Credentials that are not tied to an organization, such as an operator's environment-configured key, are unaffected. An organization administrator signed in to the dashboard can now list, read and revoke their own organization's tokens through these operations, which an organization-scoped API key still cannot do. Before upgrading a management plane that serves more than one organization, re-scope by hand any user tokens still stamped with the placeholder organization "default": until you do, the organization that owns them can no longer read or revoke them.

What it does: Revoke user token Revokes a user token by its JTI (JWT ID).

Request fields:

FieldRequiredDescription
jtinoJWT ID (jti) of the token to revoke.
reasonnoOptional human-readable revocation reason (audit trail).
customer_idnoCustomer that owns the token. Optional for compatibility: a credential bound to a customer is confined to it whether or not this is set, and naming a different customer is denied.

Response fields:

FieldRequiredDescription
successnoTrue if the token was revoked.
revoked_atnoWhen the revocation took effect.
{"signatures":{"go":"func (x *AdminClient) RevokeUserToken(ctx context.Context, req *adminv1.RevokeUserTokenRequest) (*adminv1.RevokeUserTokenResponse, error)","python":"revoke_user_token(req: admin_pb2.RevokeUserTokenRequest) -\u003e RevokeUserTokenResponse","typescript":"revokeUserToken(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RevokeUserTokenRequestSchema\u003e): Promise\u003cRevokeUserTokenResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/user-tokens/01H...:revoke\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\",\n    \"customer_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RevokeUserTokenRequest{}\n\n\tresp, err := client.Admin().RevokeUserToken(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/admin/revokeusertoken\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.admin.v1 import admin_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 = admin_pb2.RevokeUserTokenRequest()\ntry:\n    result = client.admin.revoke_user_token(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.admin.revokeUserToken(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/user-tokens/01H...:revoke\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\",\n    \"customer_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/user-tokens/{jti}:revoke","slug":"revoke-user-token"}

Create telemetry config

What it does: Create telemetry config

Request fields:

FieldRequiredDescription
user_idnoOwner of the forwarding config.
telemetry_typenoSignal type to forward: traces, metrics, logs, or audit_logs.
sink_urlnoDestination OTLP sink URL.
protocolnoOTLP wire protocol for the sink.
auth_typenoAuthentication scheme for the sink.
auth_valuenoundocumented
api_key_headernoHeader name to carry the key when auth_type is api_key.
enablednoWhether forwarding starts enabled (default enabled if unset).
forward_interval_secondsnoAudit-log forward interval in seconds (default 300 if unset).

Response fields:

FieldRequiredDescription
confignoThe created forwarding config (auth_value decrypted).
{"signatures":{"go":"func (x *AdminClient) CreateTelemetryConfig(ctx context.Context, req *adminv1.CreateTelemetryConfigRequest) (*adminv1.CreateTelemetryConfigResponse, error)","python":"create_telemetry_config(req: admin_pb2.CreateTelemetryConfigRequest) -\u003e CreateTelemetryConfigResponse","typescript":"createTelemetryConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateTelemetryConfigRequestSchema\u003e): Promise\u003cCreateTelemetryConfigResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"telemetry_type\": \"...\",\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"enabled\": false,\n    \"forward_interval_seconds\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateTelemetryConfigRequest{}\n\n\tresp, err := client.Admin().CreateTelemetryConfig(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/admin/createtelemetryconfig\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.admin.v1 import admin_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 = admin_pb2.CreateTelemetryConfigRequest()\ntry:\n    result = client.admin.create_telemetry_config(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.admin.createTelemetryConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/telemetry-configs\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"telemetry_type\": \"...\",\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"enabled\": false,\n    \"forward_interval_seconds\": 0\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/telemetry-configs","slug":"create-telemetry-config"}

List telemetry configs

What it does: List telemetry configs

Request fields:

FieldRequiredDescription
user_idnoundocumented
telemetry_typenoOptional filter by signal type.
enablednoundocumented

Response fields:

FieldRequiredDescription
configsnoMatching forwarding configs.
totalnoTotal number of matching configs.
{"signatures":{"go":"func (x *AdminClient) ListTelemetryConfigs(ctx context.Context, req *adminv1.ListTelemetryConfigsRequest) (*adminv1.ListTelemetryConfigsResponse, error)","python":"list_telemetry_configs(req: admin_pb2.ListTelemetryConfigsRequest) -\u003e ListTelemetryConfigsResponse","typescript":"listTelemetryConfigs(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListTelemetryConfigsRequestSchema\u003e): Promise\u003cListTelemetryConfigsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListTelemetryConfigsRequest{}\n\n\tresp, err := client.Admin().ListTelemetryConfigs(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/admin/listtelemetryconfigs\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.admin.v1 import admin_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 = admin_pb2.ListTelemetryConfigsRequest()\ntry:\n    result = client.admin.list_telemetry_configs(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.admin.listTelemetryConfigs(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/telemetry-configs\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/telemetry-configs","slug":"list-telemetry-configs"}

Get telemetry config

What it does: Get telemetry config

Request fields:

FieldRequiredDescription
idnoForwarding config ID to fetch.

Response fields:

FieldRequiredDescription
confignoThe requested forwarding config.
{"signatures":{"go":"func (x *AdminClient) GetTelemetryConfig(ctx context.Context, req *adminv1.GetTelemetryConfigRequest) (*adminv1.GetTelemetryConfigResponse, error)","python":"get_telemetry_config(req: admin_pb2.GetTelemetryConfigRequest) -\u003e GetTelemetryConfigResponse","typescript":"getTelemetryConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetTelemetryConfigRequestSchema\u003e): Promise\u003cGetTelemetryConfigResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetTelemetryConfigRequest{}\n\n\tresp, err := client.Admin().GetTelemetryConfig(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/admin/gettelemetryconfig\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.admin.v1 import admin_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 = admin_pb2.GetTelemetryConfigRequest()\ntry:\n    result = client.admin.get_telemetry_config(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.admin.getTelemetryConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/telemetry-configs/{id}","slug":"get-telemetry-config"}

Update telemetry config

What it does: Update telemetry config

Request fields:

FieldRequiredDescription
idnoForwarding config ID to update.
sink_urlnoNew sink URL; unset leaves it unchanged.
protocolnoNew OTLP protocol; unset leaves it unchanged.
auth_typenoNew auth scheme; unset leaves it unchanged.
auth_valuenoundocumented
api_key_headernoNew API key header name; unset leaves it unchanged.
enablednoNew enabled flag; unset leaves it unchanged.
statusnoOverride the connection status (connected/disconnected/error/testing).
forward_interval_secondsnoNew audit-log forward interval in seconds; unset leaves it unchanged.

Response fields:

FieldRequiredDescription
confignoThe updated forwarding config.
{"signatures":{"go":"func (x *AdminClient) UpdateTelemetryConfig(ctx context.Context, req *adminv1.UpdateTelemetryConfigRequest) (*adminv1.UpdateTelemetryConfigResponse, error)","python":"update_telemetry_config(req: admin_pb2.UpdateTelemetryConfigRequest) -\u003e UpdateTelemetryConfigResponse","typescript":"updateTelemetryConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateTelemetryConfigRequestSchema\u003e): Promise\u003cUpdateTelemetryConfigResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"enabled\": false,\n    \"status\": \"...\",\n    \"forward_interval_seconds\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateTelemetryConfigRequest{}\n\n\tresp, err := client.Admin().UpdateTelemetryConfig(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/admin/updatetelemetryconfig\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.admin.v1 import admin_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 = admin_pb2.UpdateTelemetryConfigRequest()\ntry:\n    result = client.admin.update_telemetry_config(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.admin.updateTelemetryConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"enabled\": false,\n    \"status\": \"...\",\n    \"forward_interval_seconds\": 0\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/telemetry-configs/{id}","slug":"update-telemetry-config"}

Delete telemetry config

What it does: Delete telemetry config

Request fields:

FieldRequiredDescription
idnoForwarding config ID to delete.

Response fields:

FieldRequiredDescription
successnoTrue if the config was deleted.
{"signatures":{"go":"func (x *AdminClient) DeleteTelemetryConfig(ctx context.Context, req *adminv1.DeleteTelemetryConfigRequest) (*adminv1.DeleteTelemetryConfigResponse, error)","python":"delete_telemetry_config(req: admin_pb2.DeleteTelemetryConfigRequest) -\u003e DeleteTelemetryConfigResponse","typescript":"deleteTelemetryConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteTelemetryConfigRequestSchema\u003e): Promise\u003cDeleteTelemetryConfigResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteTelemetryConfigRequest{}\n\n\tresp, err := client.Admin().DeleteTelemetryConfig(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/admin/deletetelemetryconfig\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.admin.v1 import admin_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 = admin_pb2.DeleteTelemetryConfigRequest()\ntry:\n    result = client.admin.delete_telemetry_config(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.admin.deleteTelemetryConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/telemetry-configs/{id}","slug":"delete-telemetry-config"}

Trigger audit forward

What it does: Trigger an immediate audit-log forward run (real-time push). The management plane kicks the in-process forwarder; the cron ticker is the backstop.

Request fields:

FieldRequiredDescription
ownernoOptional owner hint for logging; the forwarder drains all due configs.
{"signatures":{"go":"func (x *AdminClient) TriggerAuditForward(ctx context.Context, req *adminv1.TriggerAuditForwardRequest) (*adminv1.TriggerAuditForwardResponse, error)","python":"trigger_audit_forward(req: admin_pb2.TriggerAuditForwardRequest) -\u003e TriggerAuditForwardResponse","typescript":"triggerAuditForward(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.TriggerAuditForwardRequestSchema\u003e): Promise\u003cTriggerAuditForwardResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/trigger-forward\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"owner\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.TriggerAuditForwardRequest{}\n\n\tresp, err := client.Admin().TriggerAuditForward(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/admin/triggerauditforward\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.admin.v1 import admin_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 = admin_pb2.TriggerAuditForwardRequest()\ntry:\n    result = client.admin.trigger_audit_forward(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.admin.triggerAuditForward(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/telemetry-configs/trigger-forward\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"owner\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/telemetry-configs/trigger-forward","slug":"trigger-audit-forward"}

Test audit forward

What it does: Test an audit-log SIEM sink by sending a synthetic OTLP-Logs record via the same path the forwarder uses (POST /v1/logs with the resolved auth). Proves the actual log endpoint + auth, unlike the trace-based bellhop tester.

Request fields:

FieldRequiredDescription
sink_urlnoSink to test (OTLP/HTTP-JSON; the /v1/logs path is appended if absent).
protocolnoWire protocol; only "http/json" is supported for audit-log forwarding.
auth_typenoAuth triple. auth_value may be a plaintext credential or a valet://sm:// reference (resolved server-side), mirroring the forwarder.
auth_valuenoundocumented
api_key_headernoundocumented
ownernoOptional owner hint for logging.

Response fields:

FieldRequiredDescription
oknoTrue if the synthetic record was accepted (2xx) by the sink.
messagenoError/diagnostic detail when ok is false.
{"signatures":{"go":"func (x *AdminClient) TestAuditForward(ctx context.Context, req *adminv1.TestAuditForwardRequest) (*adminv1.TestAuditForwardResponse, error)","python":"test_audit_forward(req: admin_pb2.TestAuditForwardRequest) -\u003e TestAuditForwardResponse","typescript":"testAuditForward(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.TestAuditForwardRequestSchema\u003e): Promise\u003cTestAuditForwardResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/telemetry-configs/test-forward\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"owner\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.TestAuditForwardRequest{}\n\n\tresp, err := client.Admin().TestAuditForward(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/admin/testauditforward\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.admin.v1 import admin_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 = admin_pb2.TestAuditForwardRequest()\ntry:\n    result = client.admin.test_audit_forward(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.admin.testAuditForward(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/telemetry-configs/test-forward\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sink_url\": \"...\",\n    \"protocol\": \"...\",\n    \"auth_type\": \"...\",\n    \"auth_value\": \"...\",\n    \"api_key_header\": \"...\",\n    \"owner\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/telemetry-configs/test-forward","slug":"test-audit-forward"}

List audit checkpoints

What it does: List signed Merkle checkpoints (fraser#4599) for chain verification: each checkpoint's prev_root chains to the previous and its signature covers the root. Ordered by seq ascending, starting strictly after after_seq.

Request fields:

FieldRequiredDescription
after_seqnoReturn checkpoints with seq strictly greater than this (0 = from the start).
limitnoMax checkpoints to return; the server applies a default and a hard cap.
rebuildnoWhen true, the server rebuilds each window from current content and fills content_root_hash/content_leaf_count, so the caller can detect content tampering (edits/deletes/back-dated inserts), not just header/signature tampering. More expensive — it reads every sealed row.

Response fields:

FieldRequiredDescription
checkpointsnoundocumented
{"signatures":{"go":"func (x *AdminClient) ListAuditCheckpoints(ctx context.Context, req *adminv1.ListAuditCheckpointsRequest) (*adminv1.ListAuditCheckpointsResponse, error)","python":"list_audit_checkpoints(req: admin_pb2.ListAuditCheckpointsRequest) -\u003e ListAuditCheckpointsResponse","typescript":"listAuditCheckpoints(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListAuditCheckpointsRequestSchema\u003e): Promise\u003cListAuditCheckpointsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/audit/checkpoints:list\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"after_seq\": 0,\n    \"limit\": 0,\n    \"rebuild\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListAuditCheckpointsRequest{}\n\n\tresp, err := client.Admin().ListAuditCheckpoints(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/admin/listauditcheckpoints\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.admin.v1 import admin_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 = admin_pb2.ListAuditCheckpointsRequest()\ntry:\n    result = client.admin.list_audit_checkpoints(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.admin.listAuditCheckpoints(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/audit/checkpoints:list\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"after_seq\": 0,\n    \"limit\": 0,\n    \"rebuild\": false\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/audit/checkpoints:list","slug":"list-audit-checkpoints"}

Get audit inclusion proof

What it does: Return the Merkle inclusion proof for an audit_logs row: its leaf hash and audit path recomputed from current content, plus the signed checkpoint it belongs to, so a verifier can confirm the row is committed to a signed root.

Request fields:

FieldRequiredDescription
audit_log_idnoundocumented

Response fields:

FieldRequiredDescription
foundnofound is false when the row is not committed to any checkpoint.
reasonnoreason explains a false found: "unsealed" (written after the last checkpoint or before the first) or "row_missing" (no such row — a possible deletion).
leaf_hashnoleaf_hash is the row's RFC 6962 leaf hash, recomputed from current content.
proofnoproof is the Merkle audit path, in leaf-to-root order.
leaf_indexnoundocumented
tree_sizenotree_size is the number of rows currently in the sealed window; a mismatch with checkpoint.leaf_count means rows were inserted or deleted after sealing.
checkpointnoundocumented
{"signatures":{"go":"func (x *AdminClient) GetAuditInclusionProof(ctx context.Context, req *adminv1.GetAuditInclusionProofRequest) (*adminv1.GetAuditInclusionProofResponse, error)","python":"get_audit_inclusion_proof(req: admin_pb2.GetAuditInclusionProofRequest) -\u003e GetAuditInclusionProofResponse","typescript":"getAuditInclusionProof(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetAuditInclusionProofRequestSchema\u003e): Promise\u003cGetAuditInclusionProofResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/audit/inclusion-proof\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"audit_log_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetAuditInclusionProofRequest{}\n\n\tresp, err := client.Admin().GetAuditInclusionProof(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/admin/getauditinclusionproof\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.admin.v1 import admin_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 = admin_pb2.GetAuditInclusionProofRequest()\ntry:\n    result = client.admin.get_audit_inclusion_proof(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.admin.getAuditInclusionProof(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/audit/inclusion-proof\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"audit_log_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/audit/inclusion-proof","slug":"get-audit-inclusion-proof"}

Query audit logs

Changed in v0.10.0 (behaviour changes): Fleet audit reads require explicit platform permissions; organization admin and audit reader scopes no longer grant fleet access. An organization admin who called these methods before keeps working, but sees only their own organization's records, and only records written from 0.10 on, because earlier records have no organization owner.

Changed in v0.10.0 (security updates): Organization-scoped audit reads show records with trusted ownership stamps; fleet-wide reads require an explicit platform audit grant.

Changed in v0.10.0 (security updates): Provisioned admin-scoped secrets also gain QueryAuditLogs and GetAuditLog, with the same fleet visibility already available through QueryPlatformAuditLogs.

Changed in v0.10.0 (deprecations): Calling the fleet audit methods as an organization admin, without a platform audit grant, is deprecated and will be refused in a later release. In 0.10 these calls return only the caller's own organization's records, and only records written from 0.10 on, because records written before the upgrade have no organization owner. The management plane logs a deprecation warning on each such call. Use QueryCustomerAuditLogs and GetCustomerAuditLog for organization reads.

Changed in v0.9.0 (behaviour changes): Audit records for changes made through the Developer Console now name the signed-in user and their email instead of the console's service key. The key ID moves to metadata.via_key. Admin Console calls that already send X-Acting-Session-Token change the same way: user_id changes from the key to the person, and metadata.via_key is added. Audit records of a user or management-key caller now also carry the caller's email.

Changed in v0.9.0 (behaviour changes): An audit record is now written in the same transaction as the change it records. A change that fails or is refused leaves one record with success set to false. Changes made through the workspace API are now audited too.

Changed in v0.9.0 (behaviour changes): The Developer Console no longer writes its own audit records for key rotation, management-key create and delete, and project telemetry changes; the server's ROTATE_CLIENT_KEY, ISSUE_MY_KEY, REVOKE_MY_KEY and CREATE_ or UPDATE_TELEMETRY_CONFIG records cover them. A legacy key rotation (no client) keeps the console record until a later release. A data plane upgrade outcome is now one FINISH_DATAPLANE_UPGRADE record with the final phase in metadata.phase; only Completed has success set to true.

Changed in v0.9.0 (behaviour changes): Until a later release removes the Admin Console's own audit records, an Admin Console change that the server audits leaves two records, and both now name the signed-in user: the console's and the server's. For example, a data plane update writes UPDATE from the console, and UPDATE_DATAPLANE with metadata.via_key from the server.

Changed in v0.9.0 (behaviour changes): Audit records of Developer Console calls now carry the browser's user_agent, and the X-Forwarded-For chain that the console received in metadata.forwarded_for. source_ip stays the address of the console.

Changed in v0.9.0 (new features): Audit log queries accept search, a case-insensitive match over the actor's email, user ID and type, the action, the resource type and ID, the correlation ID, the endpoint, the source IP and the error message. They also accept order_by, which sorts by actor, action, resource, source or outcome. A search that sets no start_time covers the 30 days before the end time (or now), from the start of that UTC day.

Changed in v0.9.0 (bug fixes): The Audit Logs page now loads quickly on a management plane with millions of audit records. It used to read the whole audit table on every load and could time out with "Couldn't load this page".

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.5.0 (behaviour changes): Audit entries from the management plane's services now record the call that produced them -- source_ip, user_agent, http_method and endpoint -- and name the user an action was performed on under the subject_user_id metadata key. Key lifecycle entries use one vocabulary: ISSUE_MY_KEY, REVOKE_MY_KEY, ROTATE_CLIENT_KEY, UPDATE_API_KEY and DELETE_API_KEY, with resource_type api_key and actor_type USER or SERVICE.

Changed in v0.5.0 (new features): QueryAuditLogs and QueryPlatformAuditLogs accept subject_user_id, which selects the entries where a user was acted upon rather than the entries they performed themselves. An admin minting a key for a service identity is now findable from either side: user_id names the admin, subject_user_id names the identity.

Changed in v0.5.0 (bug fixes): Scoped management API keys can now reach audit-log and metrics operations without organization or project fields. The handler applies the relevant workspace, organization or platform boundary for each operation.

Changed in v0.2.0 (new features): The audit log query RPCs (QueryAuditLogs and QueryPlatformAuditLogs) can now return success and failure counts alongside the page of entries. Set include_stats and read the new stats field instead of running an extra query per count. The counts obey every filter except success, so a view filtered to one outcome still shows both numbers. The response is unchanged when include_stats is not set.

What it does: Query stored audit_logs entries with filtering and pagination. The read complement to the SIEM forwarder (which only exports) and the checkpoint verification RPCs (which only prove tamper-evidence): list and inspect entries over the API instead of standing up a SIEM.

Request fields:

FieldRequiredDescription
user_idnoFilter by the user id that performed the action.
actor_typenoFilter by actor type (e.g. "user", "system", "service_account").
action_typenoFilter by action type (e.g. "CREATE", "UPDATE", "DELETE", "UPGRADE").
resource_typenoFilter by resource type (e.g. "provider", "api_key", "dataplane").
resource_idnoFilter by the affected resource id.
successnoFilter by outcome; unset matches both successes and failures.
correlation_idnoFilter by correlation id (groups related entries from one operation).
start_timenoStart of the time range, inclusive.
end_timenoEnd of the time range, exclusive.
page_sizenoMax entries per page; the server applies a default (50) and a hard cap (1000).
page_tokennoOpaque token from a prior response's next_page_token.
order_directionnoSort direction: "asc" or "desc" (default "desc", newest first). Applies to order_by, which defaults to the timestamp.
include_statsnoWhen true the response carries stats, the success/failure split computed in the same database round trip as total_count. Lets a summary UI render total/success/failure from one call instead of one page_size=1 query per aggregate.
subject_user_idnoFilter by the user the action was performed ON, which is not always the user who performed it: an admin minting a key for a service identity puts the admin in user_id and the identity here. Ask "what was done to this user" with this field and "what did this user do" with user_id.
searchnoFree-text search: a case-insensitive substring match over user_email, user_id, actor_type, action_type, resource_type, resource_id, correlation_id, endpoint, source_ip and error_message. %, _ and \ match as literal characters. total_count and stats apply it too. Empty or whitespace-only means no search. A search with no start_time reads only from the start of the UTC day 30 days before the end time (end_time, or now when end_time is unset); set start_time to search further back.
order_bynoSort key: "timestamp", "actor" (user_email, user_id), "action", "resource" (resource_type, resource_id), "source" (source_ip) or "outcome" (success). Empty means "timestamp". order_direction applies to the key; a key other than timestamp puts empty values last and breaks ties by timestamp and id, newest first, so pages stay stable. A sort alone does not narrow the time window; only a search does.

Response fields:

FieldRequiredDescription
logsnoundocumented
next_page_tokennoToken to pass back as page_token for the next page; empty when exhausted.
total_countnoTotal number of matching entries across all pages. Unlike stats, this honours the success filter -- it is the count this page is paging through.
statsnoOutcome split; present only when the request set include_stats.
{"signatures":{"go":"func (x *AdminClient) QueryAuditLogs(ctx context.Context, req *adminv1.QueryAuditLogsRequest) (*adminv1.QueryAuditLogsResponse, error)","python":"query_audit_logs(req: admin_pb2.QueryAuditLogsRequest) -\u003e QueryAuditLogsResponse","typescript":"queryAuditLogs(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.QueryAuditLogsRequestSchema\u003e): Promise\u003cQueryAuditLogsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"actor_type\": \"...\",\n    \"action_type\": \"...\",\n    \"resource_type\": \"...\",\n    \"resource_id\": \"...\",\n    \"success\": false,\n    \"correlation_id\": \"...\",\n    \"start_time\": {},\n    \"end_time\": {},\n    \"page_size\": 0,\n    \"page_token\": \"...\",\n    \"order_direction\": \"...\",\n    \"include_stats\": false,\n    \"subject_user_id\": \"...\",\n    \"search\": \"...\",\n    \"order_by\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.QueryAuditLogsRequest{}\n\n\tresp, err := client.Admin().QueryAuditLogs(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/admin/queryauditlogs\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.admin.v1 import admin_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 = admin_pb2.QueryAuditLogsRequest()\ntry:\n    result = client.admin.query_audit_logs(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.admin.queryAuditLogs(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"actor_type\": \"...\",\n    \"action_type\": \"...\",\n    \"resource_type\": \"...\",\n    \"resource_id\": \"...\",\n    \"success\": false,\n    \"correlation_id\": \"...\",\n    \"start_time\": {},\n    \"end_time\": {},\n    \"page_size\": 0,\n    \"page_token\": \"...\",\n    \"order_direction\": \"...\",\n    \"include_stats\": false,\n    \"subject_user_id\": \"...\",\n    \"search\": \"...\",\n    \"order_by\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/audit/logs:query","slug":"query-audit-logs"}

Get audit log

Changed in v0.10.0 (behaviour changes): Fleet audit reads require explicit platform permissions; organization admin and audit reader scopes no longer grant fleet access. An organization admin who called these methods before keeps working, but sees only their own organization's records, and only records written from 0.10 on, because earlier records have no organization owner.

Changed in v0.10.0 (security updates): Organization-scoped audit reads show records with trusted ownership stamps; fleet-wide reads require an explicit platform audit grant.

Changed in v0.10.0 (security updates): Provisioned admin-scoped secrets also gain QueryAuditLogs and GetAuditLog, with the same fleet visibility already available through QueryPlatformAuditLogs.

Changed in v0.10.0 (deprecations): Calling the fleet audit methods as an organization admin, without a platform audit grant, is deprecated and will be refused in a later release. In 0.10 these calls return only the caller's own organization's records, and only records written from 0.10 on, because records written before the upgrade have no organization owner. The management plane logs a deprecation warning on each such call. Use QueryCustomerAuditLogs and GetCustomerAuditLog for organization reads.

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.5.0 (bug fixes): Scoped management API keys can now reach audit-log and metrics operations without organization or project fields. The handler applies the relevant workspace, organization or platform boundary for each operation.

What it does: Get a single audit_logs entry by id.

Request fields:

FieldRequiredDescription
idnoUUID of the audit log entry to fetch.

Response fields:

FieldRequiredDescription
idnoServer-generated audit entry UUID (primary key).
timestampnoWhen the audited action occurred.
user_idnoId of the user that performed the action; empty for system actions.
user_emailnoEmail of the acting user, captured at write time.
actor_typenoActor category (e.g. "user", "system", "service_account").
action_typenoAction performed (e.g. "CREATE", "UPDATE", "DELETE", "UPGRADE").
resource_typenoType of the affected resource (e.g. "provider", "api_key", "dataplane").
resource_idnoId of the affected resource.
source_ipnoClient IP the request originated from.
user_agentnoUser-Agent header of the originating request.
http_methodnoHTTP method of the originating request (e.g. "POST").
endpointnoRequest path / RPC endpoint that triggered the action.
status_codenoHTTP status code of the response.
successnoWhether the action succeeded.
request_paramsnoRequest path/query parameters captured for the action.
request_bodynoRequest body captured for the action (sensitive values may be redacted).
response_datanoResponse payload captured for the action.
error_messagenoError detail when the action failed; empty on success.
correlation_idnoCorrelation id grouping related entries from one operation.
metadatanoAdditional structured context attached to the entry.
created_atnoWhen the audit row was persisted (defaults to the event time).
{"signatures":{"go":"func (x *AdminClient) GetAuditLog(ctx context.Context, req *adminv1.GetAuditLogRequest) (*adminv1.AuditLogEntry, error)","python":"get_audit_log(req: admin_pb2.GetAuditLogRequest) -\u003e AuditLogEntry","typescript":"getAuditLog(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetAuditLogRequestSchema\u003e): Promise\u003cAuditLogEntry\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/audit/logs/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetAuditLogRequest{}\n\n\tresp, err := client.Admin().GetAuditLog(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/admin/getauditlog\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.admin.v1 import admin_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 = admin_pb2.GetAuditLogRequest()\ntry:\n    result = client.admin.get_audit_log(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.admin.getAuditLog(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/audit/logs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/audit/logs/{id}","slug":"get-audit-log"}

Query platform audit logs

Changed in v0.11.0 (bug fixes): A request with a NUL character in a name, description or filter field now returns 400 invalid_argument. It returned 500 internal before, which clients retry and which counted as a server failure. This applies when the management plane uses the extended query protocol, which is the default. A deployment that sets global.useSimpleProtocol (USE_QUERY_EXEC_MODE_SIMPLE_PROTOCOL=true, used with pgbouncer) still returns 500 for these requests.

Changed in v0.10.0 (behaviour changes): Fleet audit reads require explicit platform permissions; organization admin and audit reader scopes no longer grant fleet access. An organization admin who called these methods before keeps working, but sees only their own organization's records, and only records written from 0.10 on, because earlier records have no organization owner.

Changed in v0.10.0 (security updates): Organization-scoped audit reads show records with trusted ownership stamps; fleet-wide reads require an explicit platform audit grant.

Changed in v0.10.0 (deprecations): Calling the fleet audit methods as an organization admin, without a platform audit grant, is deprecated and will be refused in a later release. In 0.10 these calls return only the caller's own organization's records, and only records written from 0.10 on, because records written before the upgrade have no organization owner. The management plane logs a deprecation warning on each such call. Use QueryCustomerAuditLogs and GetCustomerAuditLog for organization reads.

Changed in v0.9.0 (behaviour changes): Audit records for changes made through the Developer Console now name the signed-in user and their email instead of the console's service key. The key ID moves to metadata.via_key. Admin Console calls that already send X-Acting-Session-Token change the same way: user_id changes from the key to the person, and metadata.via_key is added. Audit records of a user or management-key caller now also carry the caller's email.

Changed in v0.9.0 (behaviour changes): An audit record is now written in the same transaction as the change it records. A change that fails or is refused leaves one record with success set to false. Changes made through the workspace API are now audited too.

Changed in v0.9.0 (behaviour changes): The Developer Console no longer writes its own audit records for key rotation, management-key create and delete, and project telemetry changes; the server's ROTATE_CLIENT_KEY, ISSUE_MY_KEY, REVOKE_MY_KEY and CREATE_ or UPDATE_TELEMETRY_CONFIG records cover them. A legacy key rotation (no client) keeps the console record until a later release. A data plane upgrade outcome is now one FINISH_DATAPLANE_UPGRADE record with the final phase in metadata.phase; only Completed has success set to true.

Changed in v0.9.0 (behaviour changes): Until a later release removes the Admin Console's own audit records, an Admin Console change that the server audits leaves two records, and both now name the signed-in user: the console's and the server's. For example, a data plane update writes UPDATE from the console, and UPDATE_DATAPLANE with metadata.via_key from the server.

Changed in v0.9.0 (behaviour changes): Audit records of Developer Console calls now carry the browser's user_agent, and the X-Forwarded-For chain that the console received in metadata.forwarded_for. source_ip stays the address of the console.

Changed in v0.9.0 (new features): Audit log queries accept search, a case-insensitive match over the actor's email, user ID and type, the action, the resource type and ID, the correlation ID, the endpoint, the source IP and the error message. They also accept order_by, which sorts by actor, action, resource, source or outcome. A search that sets no start_time covers the 30 days before the end time (or now), from the start of that UTC day.

Changed in v0.9.0 (bug fixes): The Audit Logs page now loads quickly on a management plane with millions of audit records. It used to read the whole audit table on every load and could time out with "Couldn't load this page".

Changed in v0.5.0 (behaviour changes): Audit entries from the management plane's services now record the call that produced them -- source_ip, user_agent, http_method and endpoint -- and name the user an action was performed on under the subject_user_id metadata key. Key lifecycle entries use one vocabulary: ISSUE_MY_KEY, REVOKE_MY_KEY, ROTATE_CLIENT_KEY, UPDATE_API_KEY and DELETE_API_KEY, with resource_type api_key and actor_type USER or SERVICE.

Changed in v0.5.0 (new features): QueryAuditLogs and QueryPlatformAuditLogs accept subject_user_id, which selects the entries where a user was acted upon rather than the entries they performed themselves. An admin minting a key for a service identity is now findable from either side: user_id names the admin, subject_user_id names the identity.

Changed in v0.2.0 (new features): The audit log query RPCs (QueryAuditLogs and QueryPlatformAuditLogs) can now return success and failure counts alongside the page of entries. Set include_stats and read the new stats field instead of running an extra query per count. The counts obey every filter except success, so a view filtered to one outcome still shows both numbers. The response is unchanged when include_stats is not set.

What it does: Is the fleet-wide audit query. It requires an explicit platform_audit_logs.read grant, such as platform_admin; organization admin scope alone does not grant fleet access. An organization admin without that grant reads only its own organization's records, which is deprecated; use QueryCustomerAuditLogs. Same request/response as QueryAuditLogs.

Request fields:

FieldRequiredDescription
user_idnoFilter by the user id that performed the action.
actor_typenoFilter by actor type (e.g. "user", "system", "service_account").
action_typenoFilter by action type (e.g. "CREATE", "UPDATE", "DELETE", "UPGRADE").
resource_typenoFilter by resource type (e.g. "provider", "api_key", "dataplane").
resource_idnoFilter by the affected resource id.
successnoFilter by outcome; unset matches both successes and failures.
correlation_idnoFilter by correlation id (groups related entries from one operation).
start_timenoStart of the time range, inclusive.
end_timenoEnd of the time range, exclusive.
page_sizenoMax entries per page; the server applies a default (50) and a hard cap (1000).
page_tokennoOpaque token from a prior response's next_page_token.
order_directionnoSort direction: "asc" or "desc" (default "desc", newest first). Applies to order_by, which defaults to the timestamp.
include_statsnoWhen true the response carries stats, the success/failure split computed in the same database round trip as total_count. Lets a summary UI render total/success/failure from one call instead of one page_size=1 query per aggregate.
subject_user_idnoFilter by the user the action was performed ON, which is not always the user who performed it: an admin minting a key for a service identity puts the admin in user_id and the identity here. Ask "what was done to this user" with this field and "what did this user do" with user_id.
searchnoFree-text search: a case-insensitive substring match over user_email, user_id, actor_type, action_type, resource_type, resource_id, correlation_id, endpoint, source_ip and error_message. %, _ and \ match as literal characters. total_count and stats apply it too. Empty or whitespace-only means no search. A search with no start_time reads only from the start of the UTC day 30 days before the end time (end_time, or now when end_time is unset); set start_time to search further back.
order_bynoSort key: "timestamp", "actor" (user_email, user_id), "action", "resource" (resource_type, resource_id), "source" (source_ip) or "outcome" (success). Empty means "timestamp". order_direction applies to the key; a key other than timestamp puts empty values last and breaks ties by timestamp and id, newest first, so pages stay stable. A sort alone does not narrow the time window; only a search does.

Response fields:

FieldRequiredDescription
logsnoundocumented
next_page_tokennoToken to pass back as page_token for the next page; empty when exhausted.
total_countnoTotal number of matching entries across all pages. Unlike stats, this honours the success filter -- it is the count this page is paging through.
statsnoOutcome split; present only when the request set include_stats.
{"signatures":{"go":"func (x *AdminClient) QueryPlatformAuditLogs(ctx context.Context, req *adminv1.QueryAuditLogsRequest) (*adminv1.QueryAuditLogsResponse, error)","python":"query_platform_audit_logs(req: admin_pb2.QueryAuditLogsRequest) -\u003e QueryAuditLogsResponse","typescript":"queryPlatformAuditLogs(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.QueryAuditLogsRequestSchema\u003e): Promise\u003cQueryAuditLogsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/platform/audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"actor_type\": \"...\",\n    \"action_type\": \"...\",\n    \"resource_type\": \"...\",\n    \"resource_id\": \"...\",\n    \"success\": false,\n    \"correlation_id\": \"...\",\n    \"start_time\": {},\n    \"end_time\": {},\n    \"page_size\": 0,\n    \"page_token\": \"...\",\n    \"order_direction\": \"...\",\n    \"include_stats\": false,\n    \"subject_user_id\": \"...\",\n    \"search\": \"...\",\n    \"order_by\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.QueryAuditLogsRequest{}\n\n\tresp, err := client.Admin().QueryPlatformAuditLogs(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/admin/queryplatformauditlogs\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.admin.v1 import admin_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 = admin_pb2.QueryAuditLogsRequest()\ntry:\n    result = client.admin.query_platform_audit_logs(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.admin.queryPlatformAuditLogs(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/platform/audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"actor_type\": \"...\",\n    \"action_type\": \"...\",\n    \"resource_type\": \"...\",\n    \"resource_id\": \"...\",\n    \"success\": false,\n    \"correlation_id\": \"...\",\n    \"start_time\": {},\n    \"end_time\": {},\n    \"page_size\": 0,\n    \"page_token\": \"...\",\n    \"order_direction\": \"...\",\n    \"include_stats\": false,\n    \"subject_user_id\": \"...\",\n    \"search\": \"...\",\n    \"order_by\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/platform/audit/logs:query","slug":"query-platform-audit-logs"}

Query customer audit logs

Changed in v0.10.0 (security updates): Organization-scoped audit reads show records with trusted ownership stamps; fleet-wide reads require an explicit platform audit grant.

Changed in v0.10.0 (new features): Organization audit log reads now include customer update and archive, project, project member, AI key, model assignment, MCP profile, MCP profile act-as, MCP OAuth client, API key, budget alert, data plane and project gateway changes, and on a single-organization deployment user role and SSO provider changes. Refused requests and fleet-wide actions stay out, and so do records written before the upgrade. That is because no earlier release writes an organization owner on an audit record.

What it does: Query audit entries owned by one customer. This read is confined to the caller's API-key customer/project boundary; it does not provide fleet visibility. Rows without a trusted ownership stamp remain platform-only.

Request fields:

FieldRequiredDescription
customer_idyesRequired tenant owner. Must match the customer bound to the API key.
project_idnoOptional project narrowing. Project-bound keys must name their bound project; organization keys may omit it to read the customer-wide set.
filtersnoAudit query filters, ordering and pagination. The tenant predicates are applied separately by the server and cannot be overridden here.

Response fields:

FieldRequiredDescription
logsnoundocumented
next_page_tokennoToken to pass back as page_token for the next page; empty when exhausted.
total_countnoTotal number of matching entries across all pages. Unlike stats, this honours the success filter -- it is the count this page is paging through.
statsnoOutcome split; present only when the request set include_stats.
{"signatures":{"go":"func (x *AdminClient) QueryCustomerAuditLogs(ctx context.Context, req *adminv1.QueryCustomerAuditLogsRequest) (*adminv1.QueryAuditLogsResponse, error)","python":"query_customer_audit_logs(req: admin_pb2.QueryCustomerAuditLogsRequest) -\u003e QueryAuditLogsResponse","typescript":"queryCustomerAuditLogs(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.QueryCustomerAuditLogsRequestSchema\u003e): Promise\u003cQueryAuditLogsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\",\n    \"filters\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.QueryCustomerAuditLogsRequest{}\n\n\tresp, err := client.Admin().QueryCustomerAuditLogs(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/admin/querycustomerauditlogs\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.admin.v1 import admin_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 = admin_pb2.QueryCustomerAuditLogsRequest()\ntry:\n    result = client.admin.query_customer_audit_logs(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.admin.queryCustomerAuditLogs(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../audit/logs:query\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\",\n    \"filters\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/audit/logs:query","slug":"query-customer-audit-logs"}

Get customer audit log

Changed in v0.10.0 (security updates): Organization-scoped audit reads show records with trusted ownership stamps; fleet-wide reads require an explicit platform audit grant.

Changed in v0.10.0 (new features): Organization audit log reads now include customer update and archive, project, project member, AI key, model assignment, MCP profile, MCP profile act-as, MCP OAuth client, API key, budget alert, data plane and project gateway changes, and on a single-organization deployment user role and SSO provider changes. Refused requests and fleet-wide actions stay out, and so do records written before the upgrade. That is because no earlier release writes an organization owner on an audit record.

What it does: Get one audit entry only when its trusted ownership matches the supplied customer and optional project boundary. A foreign UUID is returned as NotFound, the same as an unknown UUID.

Request fields:

FieldRequiredDescription
customer_idyesRequired tenant owner. Must match the customer bound to the API key.
project_idnoOptional project narrowing. Required for a project-bound API key.
idnoUUID of the entry to fetch.

Response fields:

FieldRequiredDescription
idnoServer-generated audit entry UUID (primary key).
timestampnoWhen the audited action occurred.
user_idnoId of the user that performed the action; empty for system actions.
user_emailnoEmail of the acting user, captured at write time.
actor_typenoActor category (e.g. "user", "system", "service_account").
action_typenoAction performed (e.g. "CREATE", "UPDATE", "DELETE", "UPGRADE").
resource_typenoType of the affected resource (e.g. "provider", "api_key", "dataplane").
resource_idnoId of the affected resource.
source_ipnoClient IP the request originated from.
user_agentnoUser-Agent header of the originating request.
http_methodnoHTTP method of the originating request (e.g. "POST").
endpointnoRequest path / RPC endpoint that triggered the action.
status_codenoHTTP status code of the response.
successnoWhether the action succeeded.
request_paramsnoRequest path/query parameters captured for the action.
request_bodynoRequest body captured for the action (sensitive values may be redacted).
response_datanoResponse payload captured for the action.
error_messagenoError detail when the action failed; empty on success.
correlation_idnoCorrelation id grouping related entries from one operation.
metadatanoAdditional structured context attached to the entry.
created_atnoWhen the audit row was persisted (defaults to the event time).
{"signatures":{"go":"func (x *AdminClient) GetCustomerAuditLog(ctx context.Context, req *adminv1.GetCustomerAuditLogRequest) (*adminv1.AuditLogEntry, error)","python":"get_customer_audit_log(req: admin_pb2.GetCustomerAuditLogRequest) -\u003e AuditLogEntry","typescript":"getCustomerAuditLog(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetCustomerAuditLogRequestSchema\u003e): Promise\u003cAuditLogEntry\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../audit/logs/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetCustomerAuditLogRequest{}\n\n\tresp, err := client.Admin().GetCustomerAuditLog(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/admin/getcustomerauditlog\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.admin.v1 import admin_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 = admin_pb2.GetCustomerAuditLogRequest()\ntry:\n    result = client.admin.get_customer_audit_log(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.admin.getCustomerAuditLog(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../audit/logs/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/audit/logs/{id}","slug":"get-customer-audit-log"}

Create customer

Changed in v0.1.5 (bug fixes): Creating an organization now rejects an organization ID that does not match the documented slug format (lowercase letters, digits, and internal hyphens, 63 characters maximum). The API previously accepted any non-empty string. Existing organizations are not affected; the check applies only when an organization is created.

Deprecated Use TenancyService.CreateCustomer instead.

Request fields:

FieldRequiredDescription
customer_idnoCaller-chosen customer slug, unique across the deployment.
namenoOptional display name.
descriptionnoOptional description.
labelsnoOptional user-defined labels.

Response fields:

FieldRequiredDescription
customernoThe newly created customer.
{"signatures":{"go":"func (x *AdminClient) CreateCustomer(ctx context.Context, req *adminv1.CreateCustomerRequest) (*adminv1.CreateCustomerResponse, error)","python":"create_customer(req: admin_pb2.CreateCustomerRequest) -\u003e CreateCustomerResponse","typescript":"createCustomer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateCustomerRequestSchema\u003e): Promise\u003cCreateCustomerResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateCustomerRequest{}\n\n\tresp, err := client.Admin().CreateCustomer(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/admin/createcustomer\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.admin.v1 import admin_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 = admin_pb2.CreateCustomerRequest()\ntry:\n    result = client.admin.create_customer(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.admin.createCustomer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"customer_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers","slug":"create-customer"}

List customers

Deprecated Use TenancyService.ListCustomers instead.

Request fields:

FieldRequiredDescription
page_sizenoMax results per page (0 = server default).
page_tokennoOpaque pagination cursor from a prior response.

Response fields:

FieldRequiredDescription
customersnoPage of customers.
next_page_tokennoCursor for the next page; empty when exhausted.
{"signatures":{"go":"func (x *AdminClient) ListCustomers(ctx context.Context, req *adminv1.ListCustomersRequest) (*adminv1.ListCustomersResponse, error)","python":"list_customers(req: admin_pb2.ListCustomersRequest) -\u003e ListCustomersResponse","typescript":"listCustomers(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListCustomersRequestSchema\u003e): Promise\u003cListCustomersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListCustomersRequest{}\n\n\tresp, err := client.Admin().ListCustomers(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/admin/listcustomers\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.admin.v1 import admin_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 = admin_pb2.ListCustomersRequest()\ntry:\n    result = client.admin.list_customers(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.admin.listCustomers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers","slug":"list-customers"}

Get customer

Deprecated Use TenancyService.GetCustomer instead.

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug to fetch.

Response fields:

FieldRequiredDescription
customernoThe requested customer.
{"signatures":{"go":"func (x *AdminClient) GetCustomer(ctx context.Context, req *adminv1.GetCustomerRequest) (*adminv1.GetCustomerResponse, error)","python":"get_customer(req: admin_pb2.GetCustomerRequest) -\u003e GetCustomerResponse","typescript":"getCustomer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetCustomerRequestSchema\u003e): Promise\u003cGetCustomerResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetCustomerRequest{}\n\n\tresp, err := client.Admin().GetCustomer(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/admin/getcustomer\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.admin.v1 import admin_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 = admin_pb2.GetCustomerRequest()\ntry:\n    result = client.admin.get_customer(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.admin.getCustomer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}","slug":"get-customer"}

Update customer

Deprecated Use TenancyService.UpdateCustomer instead.

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug to update.
namenoNew display name; unset leaves it unchanged.
descriptionnoNew description; unset leaves it unchanged.
labelsnoReplacement set of labels.

Response fields:

FieldRequiredDescription
customernoThe updated customer.
{"signatures":{"go":"func (x *AdminClient) UpdateCustomer(ctx context.Context, req *adminv1.UpdateCustomerRequest) (*adminv1.UpdateCustomerResponse, error)","python":"update_customer(req: admin_pb2.UpdateCustomerRequest) -\u003e UpdateCustomerResponse","typescript":"updateCustomer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateCustomerRequestSchema\u003e): Promise\u003cUpdateCustomerResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateCustomerRequest{}\n\n\tresp, err := client.Admin().UpdateCustomer(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/admin/updatecustomer\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.admin.v1 import admin_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 = admin_pb2.UpdateCustomerRequest()\ntry:\n    result = client.admin.update_customer(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.admin.updateCustomer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/customers/{customer_id}","slug":"update-customer"}

Delete customer

Deprecated Use TenancyService.ArchiveCustomer instead.

soft-delete rename; returns Empty, so the old success/deleted_at response fields go away

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug to soft-delete.

Response fields:

FieldRequiredDescription
successnoTrue if the customer was deleted.
deleted_atnoWhen the soft delete took effect.
{"signatures":{"go":"func (x *AdminClient) DeleteCustomer(ctx context.Context, req *adminv1.DeleteCustomerRequest) (*adminv1.DeleteCustomerResponse, error)","python":"delete_customer(req: admin_pb2.DeleteCustomerRequest) -\u003e DeleteCustomerResponse","typescript":"deleteCustomer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteCustomerRequestSchema\u003e): Promise\u003cDeleteCustomerResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteCustomerRequest{}\n\n\tresp, err := client.Admin().DeleteCustomer(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/admin/deletecustomer\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.admin.v1 import admin_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 = admin_pb2.DeleteCustomerRequest()\ntry:\n    result = client.admin.delete_customer(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.admin.deleteCustomer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}","slug":"delete-customer"}

Create project

Changed in v0.1.5 (bug fixes): A project created through the admin API now starts with its caller as an administrator, so it can be managed and have keys minted right away. Previously a project created this way could come out with no members: its management page read "unavailable" and nobody could administer it or mint keys for its users. A caller with no resolvable user identity (a legacy admin API key) still creates an unowned project, now recorded so it can be found and repaired.

Deprecated Use ProjectsService.CreateProject instead.

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug that will own the project.
project_idnoCaller-chosen project slug, unique within the customer.
namenoOptional display name.
descriptionnoOptional description.
labelsnoOptional user-defined labels.

Response fields:

FieldRequiredDescription
projectnoThe newly created project.
{"signatures":{"go":"func (x *AdminClient) CreateProject(ctx context.Context, req *adminv1.CreateProjectRequest) (*adminv1.CreateProjectResponse, error)","python":"create_project(req: admin_pb2.CreateProjectRequest) -\u003e CreateProjectResponse","typescript":"createProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.CreateProjectRequestSchema\u003e): Promise\u003cCreateProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.CreateProjectRequest{}\n\n\tresp, err := client.Admin().CreateProject(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/admin/createproject\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.admin.v1 import admin_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 = admin_pb2.CreateProjectRequest()\ntry:\n    result = client.admin.create_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.admin.createProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"...\",\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects","slug":"create-project"}

List projects

Changed in v0.9.0 (new features): Projects now carry preferred_endpoint_url, the address a project owner starred, as tenancy.v1 projects do.

Changed in v0.1.5 (bug fixes): Listing projects now paginates. The project list endpoints accepted a page token and ignored it, always reporting that no further pages existed, so a organization with more projects than one page silently saw only the first, and a caller had no way to tell a full page from a truncated one. Callers that follow the next-page token now receive every project.

Changed in v0.1.5 (bug fixes): Projects can now be listed in a requested order, by creation time or by project id, so a client no longer has to re-sort every response. An unsupported sort field, or a filter expression the endpoint does not implement, is now rejected with a clear error rather than silently ignored, which previously returned an unsorted or unfiltered list that looked like an answer.

Deprecated Use ProjectsService.ListProjects instead.

Request fields:

FieldRequiredDescription
customer_idnoCustomer slug whose projects to list.
page_sizenoMax results per page (0 = server default).
page_tokennoOpaque pagination cursor from a prior response.

Response fields:

FieldRequiredDescription
projectsnoPage of projects.
next_page_tokennoCursor for the next page; empty when exhausted.
{"signatures":{"go":"func (x *AdminClient) ListProjects(ctx context.Context, req *adminv1.ListProjectsRequest) (*adminv1.ListProjectsResponse, error)","python":"list_projects(req: admin_pb2.ListProjectsRequest) -\u003e ListProjectsResponse","typescript":"listProjects(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectsRequestSchema\u003e): Promise\u003cListProjectsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectsRequest{}\n\n\tresp, err := client.Admin().ListProjects(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/admin/listprojects\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.admin.v1 import admin_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 = admin_pb2.ListProjectsRequest()\ntry:\n    result = client.admin.list_projects(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.admin.listProjects(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects","slug":"list-projects"}

Ensure default project

Changed in v0.9.0 (new features): EnsureDefaultProject creates an organization's default project when it does not exist yet, with the enabled providers, MCP servers and models, and returns it. An existing default project is returned as it is, so an allow-list that you emptied stays empty.

Changed in v0.9.0 (new features): Projects now carry preferred_endpoint_url, the address a project owner starred, as tenancy.v1 projects do.

What it does: Creates the customer's reserved default project when it does not exist, seeded with the enabled providers, MCP servers and models, and returns it. An existing default project is returned unchanged, so an allow-list an operator emptied stays empty (fraser#7281). The Admin Console calls it in place of its own seed (fraser#10810). Idempotent and safe to call concurrently.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.

Response fields:

FieldRequiredDescription
projectnoThe customer's default project.
{"signatures":{"go":"func (x *AdminClient) EnsureDefaultProject(ctx context.Context, req *adminv1.EnsureDefaultProjectRequest) (*adminv1.EnsureDefaultProjectResponse, error)","python":"ensure_default_project(req: admin_pb2.EnsureDefaultProjectRequest) -\u003e EnsureDefaultProjectResponse","typescript":"ensureDefaultProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.EnsureDefaultProjectRequestSchema\u003e): Promise\u003cEnsureDefaultProjectResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/default:ensure\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.EnsureDefaultProjectRequest{}\n\n\tresp, err := client.Admin().EnsureDefaultProject(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/admin/ensuredefaultproject\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.admin.v1 import admin_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 = admin_pb2.EnsureDefaultProjectRequest()\ntry:\n    result = client.admin.ensure_default_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.admin.ensureDefaultProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/default:ensure\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/default:ensure","slug":"ensure-default-project"}

Get project

Changed in v0.9.0 (new features): Projects now carry preferred_endpoint_url, the address a project owner starred, as tenancy.v1 projects do.

Deprecated Use ProjectsService.GetProject instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject slug to fetch.

Response fields:

FieldRequiredDescription
projectnoThe requested project.
{"signatures":{"go":"func (x *AdminClient) GetProject(ctx context.Context, req *adminv1.GetProjectRequest) (*adminv1.GetProjectResponse, error)","python":"get_project(req: admin_pb2.GetProjectRequest) -\u003e GetProjectResponse","typescript":"getProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetProjectRequestSchema\u003e): Promise\u003cGetProjectResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetProjectRequest{}\n\n\tresp, err := client.Admin().GetProject(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/admin/getproject\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.admin.v1 import admin_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 = admin_pb2.GetProjectRequest()\ntry:\n    result = client.admin.get_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.admin.getProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}","slug":"get-project"}

Update project

Changed in v0.11.0 (bug fixes): A request with a NUL character in a name, description or filter field now returns 400 invalid_argument. It returned 500 internal before, which clients retry and which counted as a server failure. This applies when the management plane uses the extended query protocol, which is the default. A deployment that sets global.useSimpleProtocol (USE_QUERY_EXEC_MODE_SIMPLE_PROTOCOL=true, used with pgbouncer) still returns 500 for these requests.

Deprecated Use ProjectsService.UpdateProject instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject slug to update.
namenoNew display name; unset leaves it unchanged.
descriptionnoNew description; unset leaves it unchanged.
labelsnoReplacement set of labels.
public_endpoint_urlnoNew project endpoint URL; unset leaves it unchanged, empty string clears it. This is the OPPOSITE of name/description above, which are assigned unconditionally — omitting those clears them, so callers must send the full tuple. The endpoint URL is tri-state precisely because it is edited from a different surface, and a rename must not silently wipe the URL developers are copying out of the console. Format-validated only — see Project.public_endpoint_url.

Response fields:

FieldRequiredDescription
projectnoThe updated project.
{"signatures":{"go":"func (x *AdminClient) UpdateProject(ctx context.Context, req *adminv1.UpdateProjectRequest) (*adminv1.UpdateProjectResponse, error)","python":"update_project(req: admin_pb2.UpdateProjectRequest) -\u003e UpdateProjectResponse","typescript":"updateProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateProjectRequestSchema\u003e): Promise\u003cUpdateProjectResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"public_endpoint_url\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateProjectRequest{}\n\n\tresp, err := client.Admin().UpdateProject(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/admin/updateproject\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.admin.v1 import admin_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 = admin_pb2.UpdateProjectRequest()\ntry:\n    result = client.admin.update_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.admin.updateProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"...\",\n    \"description\": \"...\",\n    \"labels\": {},\n    \"public_endpoint_url\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}","slug":"update-project"}

Delete project

Changed in v0.11.0 (behaviour changes): Deleting or archiving a project now also hides the API keys that were revoked before it, so a new project with the same name does not list them as its own. ListApiKeys reports these keys as API_KEY_STATUS_DELETED, not API_KEY_STATUS_REVOKED; each keeps its revocation stamp and stays on the data plane's revocation list.

Changed in v0.8.0 (bug fixes): Getting, setting or deleting a project setting now returns NOT_FOUND when the project is missing or deleted. Deleting a project now deletes its settings, so a new project with the same name starts with none. The default project is still created on demand.

Changed in v0.7.0 (behaviour changes): Deleting a project now revokes the API keys scoped to it, rather than refusing while any of them is live. Previously an administrator revoked each key by hand and only then deleted the project. The revoked keys stop being accepted at once, and each data plane drops the routes they carried at its next configuration update.

Changed in v0.7.0 (new features): DeleteProject now answers with the data planes whose label for the project it removed, so a caller confirming a delete reads the affected fleet out of the delete's own response rather than a follow-up call. Each of them serves the configuration it last pulled until its next pull lands, so the list names what is now clearing rather than what has cleared, and GetProjectDeletionImpact reports how far each has got.

Changed in v0.7.0 (bug fixes): Deleting a project that shares a gateway with another project no longer stops that gateway serving the other project, and the deletion receipt now reports the data plane as cleared as soon as the data plane acknowledges configuration that no longer carries the deleted project. Before, that data plane stayed clearing indefinitely.

Changed in v0.6.0 (bug fixes): Deleting a project now also deletes its project fallback overrides, so a project created later with the same ID starts with none. The upgrade removes overrides left behind by projects deleted earlier, unless a new project already uses the same ID: that project keeps them, and an admin who doesn't want them removes them on the Fallback page.

Deprecated Use ProjectsService.ArchiveProject instead.

soft-delete rename; returns Empty, so the old success/deleted_at response fields go away

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject slug to soft-delete.

Response fields:

FieldRequiredDescription
successnoTrue if the project was deleted.
deleted_atnoWhen the soft delete took effect.
clearing_dataplanesnoThe data planes whose label for this project the delete removed, ascending (fraser#9424). Each of them serves the configuration it last pulled until its next pull lands, so this names what is now clearing rather than what has cleared; GetProjectDeletionImpact reports how far each one has got.
{"signatures":{"go":"func (x *AdminClient) DeleteProject(ctx context.Context, req *adminv1.DeleteProjectRequest) (*adminv1.DeleteProjectResponse, error)","python":"delete_project(req: admin_pb2.DeleteProjectRequest) -\u003e DeleteProjectResponse","typescript":"deleteProject(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteProjectRequestSchema\u003e): Promise\u003cDeleteProjectResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteProjectRequest{}\n\n\tresp, err := client.Admin().DeleteProject(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/admin/deleteproject\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.admin.v1 import admin_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 = admin_pb2.DeleteProjectRequest()\ntry:\n    result = client.admin.delete_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.admin.deleteProject(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}","slug":"delete-project"}

List project dataplanes

Changed in v0.7.0 (new features): You can now ask which data planes serve a project. ListProjectDataplanes answers with the data planes carrying the project's label and where each one stands in serving it, and a project no data plane serves answers an empty list rather than an error. It answers on every deployment, unlike ListProjectGatewayMembers beside it, which stays Enterprise-only and keyed on gateways.

Changed in v0.7.0 (new features): Each project label now says when that data plane first answered a request for the project successfully, in a new verified_at field. It is per project and data plane, so another project's traffic on the same data plane never sets it, and applying a label again clears it until the next success. Each label also reports the config pull before it, as target_revision, held_revision and config_current.

What it does: List the data planes serving a project, which is the project's serving view (fraser#9573). The answer comes from the project labels a data plane carries (dataplane_projects, fraser#8587): a data plane serves the configuration of every project labeled on it, so the label set IS the set of data planes serving the project. The gateway a data plane hosts does not enter the question, which is why this read answers where ListProjectGatewayMembers does not. Available on EVERY deployment shape. A data plane carries project labels on SaaS exactly as it does on Enterprise, so nothing here is gated on the deployment product — the Enterprise-only surface is several gateways serving one project, and this RPC names no gateway. A project that no data plane serves answers an EMPTY list rather than an error. That state is normal: a project is created without infrastructure and stays unlabeled until a platform admin labels a data plane with it. Responses carry identity and state only, never credential material.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose data planes to list. Carries the project_id_field marker so a project_owner caller is authorized against the project it names.

Response fields:

FieldRequiredDescription
dataplanesnoOne line per data plane carrying the project's label, ascending by dataplane_id. Empty for a project no data plane serves, which is a valid state rather than an error.
{"signatures":{"go":"func (x *AdminClient) ListProjectDataplanes(ctx context.Context, req *adminv1.ListProjectDataplanesRequest) (*adminv1.ListProjectDataplanesResponse, error)","python":"list_project_dataplanes(req: admin_pb2.ListProjectDataplanesRequest) -\u003e ListProjectDataplanesResponse","typescript":"listProjectDataplanes(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectDataplanesRequestSchema\u003e): Promise\u003cListProjectDataplanesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../dataplanes\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectDataplanesRequest{}\n\n\tresp, err := client.Admin().ListProjectDataplanes(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/admin/listprojectdataplanes\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.admin.v1 import admin_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 = admin_pb2.ListProjectDataplanesRequest()\ntry:\n    result = client.admin.list_project_dataplanes(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.admin.listProjectDataplanes(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../dataplanes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/dataplanes","slug":"list-project-dataplanes"}

Get project deletion impact

Changed in v0.11.0 (new features): GetProjectDeletionImpact previews what deleting a live project removes: the project's id, and the number of users, model assignments, API keys, revoked API keys, settings, fallback policies, provider grants, MCP server grants, MCP profiles, OIDC contracts and role bindings granted directly at the project's scope. All counts except users and model assignments use the delete's own rules, and all twelve fields are empty after the delete.

Changed in v0.7.0 (new features): GetProjectDeletionImpact reads what deleting a project costs, and how far a delete under way has got. Before the delete it names every data plane serving the project. After it, each reads CLEARING until every gateway it hosted for the project acknowledged the zeroized configuration, then CLEARED with the time the last did. One still hosting a gateway joined to the project stays CLEARING; one carrying neither a membership nor a joined gateway is absent.

Changed in v0.7.0 (bug fixes): Deleting a project that shares a gateway with another project no longer stops that gateway serving the other project, and the deletion receipt now reports the data plane as cleared as soon as the data plane acknowledges configuration that no longer carries the deleted project. Before, that data plane stayed clearing indefinitely.

What it does: Report what deleting a project takes off the fleet, and how far that has got (fraser#9424). One call answers both halves of the operation: before the delete it names every data plane carrying the project's label, which is the blast radius an operator confirms; after it, the same data planes say whether each has cleared the project's configuration or is still serving what it last pulled. The reading is per data plane rather than per gateway (fraser#8587). A data plane hosting several of the project's gateways is one line, and it reads CLEARED only once every one of them has acknowledged the zeroized revision. What puts a data plane in the receipt is a membership this delete unwound, or a gateway still joined to the project. A gateway joined with no membership behind it is a stranded re-attach and holds its data plane at CLEARING, because it serves the project and has acknowledged nothing for it. What this RPC cannot see after the delete is a data plane that carried the label with neither of those left on it. Nothing sent it a zeroized revision, so there is no acknowledgement to wait for, and it leaves the receipt with the project. The membership ledger is what records the unwind, and a label is not a substitute for one. The receipt covers THIS delete and no earlier one. A gateway that left the project before it was deleted took the project off its data plane then, and the delete found nothing there to remove, so that data plane is absent from the receipt exactly as it was absent from the confirmation. A data plane is named by where its gateway sits when the receipt is read, not by where the membership was when it detached, because the ledger records the gateway and the gateway records the data plane (fraser#8587 re-keys that). Moving a gateway between data planes after the delete therefore moves its line with it. Moving a gateway also tears down its configuration on the data plane it leaves, so the one that ends up named is never a data plane still serving the project; what is lost is which data plane acknowledged. A slug deleted and then recreated reports the NEW project: this reads the live incarnation whenever one exists, so a receipt has to be read before the slug is reused. Compare project_uuid with the id read before the delete to detect this. While the project is live the response also previews what the delete removes (fraser#6371): the project's id and five counts, read in one snapshot. In JSON a zero count is left out, so a missing count is 0.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject slug whose deletion is being previewed or verified. A deleted slug is a valid argument: reading the receipt is the point.

Response fields:

FieldRequiredDescription
dataplanesnoOne line per data plane, by data plane id. Empty for a project no data plane serves, which is a valid state rather than an error: deleting it takes nothing off the fleet.
project_livenoTrue while the project exists. False reports a deletion that has already happened, so every line is CLEARING or CLEARED.
project_uuidoutput-onlyThe id of the live project. The slug is reusable, so this names the project a delete would remove. Set only while project_live is true.
member_countoutput-onlyThe project's members, not counting deleted users. Banned users count. Set only while project_live is true.
model_assignment_countoutput-onlyThe project's model assignments, not counting a model that no longer exists. Set only while project_live is true.
api_key_countoutput-onlyThe live keys the delete revokes: those ListApiKeys reports as API_KEY_STATUS_ACTIVE or API_KEY_STATUS_INACTIVE. Set only while project_live is true.
revoked_api_key_countoutput-onlyThe keys revoked before the delete, which the delete hides: those ListApiKeys reports as API_KEY_STATUS_REVOKED, and as API_KEY_STATUS_DELETED after the delete. They stay on the revocation list. Set only while project_live is true.
setting_countoutput-onlyThe project's settings, which the delete removes. Set only while project_live is true.
fallback_policy_countoutput-onlyThe project's fallback policies, active or not, which the delete removes together with their entries. Set only while project_live is true.
provider_allowlist_countoutput-onlyThe providers granted to the project, which the delete removes. Set only while project_live is true.
mcp_server_grant_countoutput-onlyThe MCP servers granted to the project, which the delete removes. Set only while project_live is true.
mcp_profile_countoutput-onlyThe live MCP profiles of the project's users, which the delete soft-deletes together with their backends. Set only while project_live is true.
oidc_config_countoutput-onlyThe project's OIDC contract, 0 or 1, which the delete removes. Set only while project_live is true.
rbac_binding_countoutput-onlyThe role bindings at the project's scope that were granted directly, to a user or a group, which the delete removes. The binding each member holds through membership is not counted here, because member_count already reports it. Set only while project_live is true.
{"signatures":{"go":"func (x *AdminClient) GetProjectDeletionImpact(ctx context.Context, req *adminv1.GetProjectDeletionImpactRequest) (*adminv1.GetProjectDeletionImpactResponse, error)","python":"get_project_deletion_impact(req: admin_pb2.GetProjectDeletionImpactRequest) -\u003e GetProjectDeletionImpactResponse","typescript":"getProjectDeletionImpact(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetProjectDeletionImpactRequestSchema\u003e): Promise\u003cGetProjectDeletionImpactResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../deletion-impact\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetProjectDeletionImpactRequest{}\n\n\tresp, err := client.Admin().GetProjectDeletionImpact(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/admin/getprojectdeletionimpact\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.admin.v1 import admin_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 = admin_pb2.GetProjectDeletionImpactRequest()\ntry:\n    result = client.admin.get_project_deletion_impact(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.admin.getProjectDeletionImpact(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../deletion-impact\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/deletion-impact","slug":"get-project-deletion-impact"}

Add project member

Changed in v0.10.0 (behaviour changes): Removing users from a project or demoting them protects assignments of the built-in Project Owner role held by users who have not been deleted. Admin memberships, custom roles and directly granted permissions do not count as Project Owner assignments.

Changed in v0.8.0 (bug fixes): Project default settings, project membership changes, the request-log mode, and rate-limit policies moved to another target now reach your gateways within the usual update cycle. They were previously saved but not pushed, so keys kept an old rate limit or fallback, a removed member kept the project's shared provider keys, and a moved policy kept limiting its old keys. A project-wide rate limit is also now enforced on keys with no settings of their own.

Changed in v0.1.5 (security updates): Adding a member to a project now rejects an identity that does not exist, instead of recording a membership and role assignment against an unknown id: records that were inert until someone was later created with the same id and inherited the access. Both API surfaces enforce this.

Changed in v0.1.5 (bug fixes): Adding a project member now fails with a 404 error when the given identity does not exist, instead of creating the membership and its RBAC binding anyway, records a user registering later with the same ID could inherit. The check and write run in one statement, so a concurrent identity deletion cannot slip through. The same call updates an existing member's role, and that path now also fails with a 404 when the member's identity was deleted. Member removal is unaffected, so cleanup of such rows still works.

Deprecated Use ProjectsService.AddProjectMember instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to add the member to.
user_idnoUser ID to add as a member.
rolenoRole to grant: "admin" or "member".

Response fields:

FieldRequiredDescription
membernoThe created membership.
{"signatures":{"go":"func (x *AdminClient) AddProjectMember(ctx context.Context, req *adminv1.AddProjectMemberRequest) (*adminv1.AddProjectMemberResponse, error)","python":"add_project_member(req: admin_pb2.AddProjectMemberRequest) -\u003e AddProjectMemberResponse","typescript":"addProjectMember(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AddProjectMemberRequestSchema\u003e): Promise\u003cAddProjectMemberResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"role\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AddProjectMemberRequest{}\n\n\tresp, err := client.Admin().AddProjectMember(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/admin/addprojectmember\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.admin.v1 import admin_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 = admin_pb2.AddProjectMemberRequest()\ntry:\n    result = client.admin.add_project_member(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.admin.addProjectMember(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\",\n    \"role\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/members","slug":"add-project-member"}

List project members

Changed in v0.1.5 (bug fixes): Listing a project's members now includes people whose access comes from a role or permission granted on that project, not only those added directly. Both let someone into the project, but only direct membership appeared on the list, so it under-reported who could reach the project, wrong for an access review or offboarding. Someone listed this way has no membership record to change, so they are reported without one, and their access is removed where it was granted rather than from the member list.

Deprecated Use ProjectsService.ListProjectMembers instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose members to list.

Response fields:

FieldRequiredDescription
membersnoAll members of the project.
{"signatures":{"go":"func (x *AdminClient) ListProjectMembers(ctx context.Context, req *adminv1.ListProjectMembersRequest) (*adminv1.ListProjectMembersResponse, error)","python":"list_project_members(req: admin_pb2.ListProjectMembersRequest) -\u003e ListProjectMembersResponse","typescript":"listProjectMembers(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectMembersRequestSchema\u003e): Promise\u003cListProjectMembersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectMembersRequest{}\n\n\tresp, err := client.Admin().ListProjectMembers(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/admin/listprojectmembers\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.admin.v1 import admin_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 = admin_pb2.ListProjectMembersRequest()\ntry:\n    result = client.admin.list_project_members(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.admin.listProjectMembers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/members","slug":"list-project-members"}

Update project member

Changed in v0.10.0 (behaviour changes): Removing users from a project or demoting them protects assignments of the built-in Project Owner role held by users who have not been deleted. Admin memberships, custom roles and directly granted permissions do not count as Project Owner assignments.

Changed in v0.3.0 (security updates): A project can no longer be left with no administrator. Demoting or removing a project's last admin through the admin or tenancy member APIs is now refused with FailedPrecondition; the mutation is allowed again as soon as a second admin exists. Previously either call could strip the final admin and orphan the project, leaving no one able to manage its members. A project whose ownership is held only through a manual role grant (not a member row) is unaffected, and revoking that grant is still done separately.

Deprecated Use ProjectsService.UpdateProjectMember instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject the member belongs to.
user_idnoUser ID of the member to update.
rolenoNew role: "admin" or "member".

Response fields:

FieldRequiredDescription
membernoThe updated membership.
{"signatures":{"go":"func (x *AdminClient) UpdateProjectMember(ctx context.Context, req *adminv1.UpdateProjectMemberRequest) (*adminv1.UpdateProjectMemberResponse, error)","python":"update_project_member(req: admin_pb2.UpdateProjectMemberRequest) -\u003e UpdateProjectMemberResponse","typescript":"updateProjectMember(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpdateProjectMemberRequestSchema\u003e): Promise\u003cUpdateProjectMemberResponse\u003e","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"role\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpdateProjectMemberRequest{}\n\n\tresp, err := client.Admin().UpdateProjectMember(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/admin/updateprojectmember\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.admin.v1 import admin_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 = admin_pb2.UpdateProjectMemberRequest()\ntry:\n    result = client.admin.update_project_member(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.admin.updateProjectMember(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PATCH \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"role\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/members/{user_id}","slug":"update-project-member"}

Remove project member

Changed in v0.10.0 (behaviour changes): Removing users from a project or demoting them protects assignments of the built-in Project Owner role held by users who have not been deleted. Admin memberships, custom roles and directly granted permissions do not count as Project Owner assignments.

Changed in v0.8.0 (bug fixes): Project default settings, project membership changes, the request-log mode, and rate-limit policies moved to another target now reach your gateways within the usual update cycle. They were previously saved but not pushed, so keys kept an old rate limit or fallback, a removed member kept the project's shared provider keys, and a moved policy kept limiting its old keys. A project-wide rate limit is also now enforced on keys with no settings of their own.

Changed in v0.3.0 (security updates): A project can no longer be left with no administrator. Demoting or removing a project's last admin through the admin or tenancy member APIs is now refused with FailedPrecondition; the mutation is allowed again as soon as a second admin exists. Previously either call could strip the final admin and orphan the project, leaving no one able to manage its members. A project whose ownership is held only through a manual role grant (not a member row) is unaffected, and revoking that grant is still done separately.

Deprecated Use ProjectsService.RemoveProjectMember instead.

identity_id replaces user_id; returns Empty, so the old success response field goes away

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to remove the member from.
user_idnoUser ID of the member to remove.

Response fields:

FieldRequiredDescription
successnoTrue if the member was removed.
{"signatures":{"go":"func (x *AdminClient) RemoveProjectMember(ctx context.Context, req *adminv1.RemoveProjectMemberRequest) (*adminv1.RemoveProjectMemberResponse, error)","python":"remove_project_member(req: admin_pb2.RemoveProjectMemberRequest) -\u003e RemoveProjectMemberResponse","typescript":"removeProjectMember(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RemoveProjectMemberRequestSchema\u003e): Promise\u003cRemoveProjectMemberResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RemoveProjectMemberRequest{}\n\n\tresp, err := client.Admin().RemoveProjectMember(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/admin/removeprojectmember\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.admin.v1 import admin_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 = admin_pb2.RemoveProjectMemberRequest()\ntry:\n    result = client.admin.remove_project_member(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.admin.removeProjectMember(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../members/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/members/{user_id}","slug":"remove-project-member"}

Ensure admin project membership

What it does: Records the intent to grant an email a role on a project (#6119). At onboarding/provisioning time the target identity row usually does not exist yet (SSO users are created lazily at first login), so the grant is parked by email and materialized at first login via ResolvePendingProjectMemberships. If the identity already exists the grant is written straight to project_members instead. Idempotent.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to grant membership on.
emailnoEmail of the intended member. Matched case-insensitively against the identity at resolution time.
rolenoRole to grant: "admin" or "member".

Response fields:

FieldRequiredDescription
enqueuednoTrue when the grant was parked as a pending row (the identity did not exist yet and will be resolved at first login); false when it was written directly to project_members because the identity already existed.
{"signatures":{"go":"func (x *AdminClient) EnsureAdminProjectMembership(ctx context.Context, req *adminv1.EnsureAdminProjectMembershipRequest) (*adminv1.EnsureAdminProjectMembershipResponse, error)","python":"ensure_admin_project_membership(req: admin_pb2.EnsureAdminProjectMembershipRequest) -\u003e EnsureAdminProjectMembershipResponse","typescript":"ensureAdminProjectMembership(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.EnsureAdminProjectMembershipRequestSchema\u003e): Promise\u003cEnsureAdminProjectMembershipResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../pending-members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"email\": \"...\",\n    \"role\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.EnsureAdminProjectMembershipRequest{}\n\n\tresp, err := client.Admin().EnsureAdminProjectMembership(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/admin/ensureadminprojectmembership\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.admin.v1 import admin_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 = admin_pb2.EnsureAdminProjectMembershipRequest()\ntry:\n    result = client.admin.ensure_admin_project_membership(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.admin.ensureAdminProjectMembership(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../pending-members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"email\": \"...\",\n    \"role\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/pending-members","slug":"ensure-admin-project-membership"}

Resolve pending project memberships

What it does: Materializes every pending email-keyed grant for (customer_id, email) into real project_members rows for user_id, then clears the resolved pending rows (#6119). Idempotent and cheap to call on every login: with no pending rows it is a no-op.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
emailnoEmail whose pending grants to resolve. Matched case-insensitively.
user_idnoIdentity id (authn.user.id) to materialize the memberships onto.

Response fields:

FieldRequiredDescription
resolved_countnoNumber of pending grants materialized into project_members rows.
{"signatures":{"go":"func (x *AdminClient) ResolvePendingProjectMemberships(ctx context.Context, req *adminv1.ResolvePendingProjectMembershipsRequest) (*adminv1.ResolvePendingProjectMembershipsResponse, error)","python":"resolve_pending_project_memberships(req: admin_pb2.ResolvePendingProjectMembershipsRequest) -\u003e ResolvePendingProjectMembershipsResponse","typescript":"resolvePendingProjectMemberships(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ResolvePendingProjectMembershipsRequestSchema\u003e): Promise\u003cResolvePendingProjectMembershipsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../pending-members:resolve\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"email\": \"...\",\n    \"user_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ResolvePendingProjectMembershipsRequest{}\n\n\tresp, err := client.Admin().ResolvePendingProjectMemberships(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/admin/resolvependingprojectmemberships\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.admin.v1 import admin_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 = admin_pb2.ResolvePendingProjectMembershipsRequest()\ntry:\n    result = client.admin.resolve_pending_project_memberships(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.admin.resolvePendingProjectMemberships(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../pending-members:resolve\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"email\": \"...\",\n    \"user_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/pending-members:resolve","slug":"resolve-pending-project-memberships"}

Ensure default project membership

Changed in v0.11.0 (new features): EnsureDefaultProjectMembership adds a user to the Users of their organization's default project when they are not in it yet, and reports whether they joined. It never changes an existing role, skips a banned user or one SCIM blocks from signing in, and writes an AUTO_JOIN_DEFAULT_PROJECT audit record when the user joins. It needs the admin management key or the project.members.add permission.

What it does: Adds user_id to the customer's default project as a member when the user has no membership there (#6526). It creates the default project first when it is missing. It never changes the role of an existing member, and it skips a user whom SCIM blocks from signing in. Idempotent: a repeat call leaves the same state and returns joined=false.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
user_idnoIdentity id (authn.user.id) to add to the default project.

Response fields:

FieldRequiredDescription
joinednoTrue when this call added the user to the default project; false when the user was already a member or SCIM blocks them from signing in.
{"signatures":{"go":"func (x *AdminClient) EnsureDefaultProjectMembership(ctx context.Context, req *adminv1.EnsureDefaultProjectMembershipRequest) (*adminv1.EnsureDefaultProjectMembershipResponse, error)","python":"ensure_default_project_membership(req: admin_pb2.EnsureDefaultProjectMembershipRequest) -\u003e EnsureDefaultProjectMembershipResponse","typescript":"ensureDefaultProjectMembership(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.EnsureDefaultProjectMembershipRequestSchema\u003e): Promise\u003cEnsureDefaultProjectMembershipResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/default/members:ensure\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.EnsureDefaultProjectMembershipRequest{}\n\n\tresp, err := client.Admin().EnsureDefaultProjectMembership(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/admin/ensuredefaultprojectmembership\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.admin.v1 import admin_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 = admin_pb2.EnsureDefaultProjectMembershipRequest()\ntry:\n    result = client.admin.ensure_default_project_membership(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.admin.ensureDefaultProjectMembership(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/default/members:ensure\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/default/members:ensure","slug":"ensure-default-project-membership"}

List models

Request fields:

FieldRequiredDescription
only_enablednoIf true, return only enabled models.

Response fields:

FieldRequiredDescription
modelsnoCatalog models matching the request.
{"signatures":{"go":"func (x *AdminClient) ListModels(ctx context.Context, req *adminv1.ListModelsRequest) (*adminv1.ListModelsResponse, error)","python":"list_models(req: admin_pb2.ListModelsRequest) -\u003e ListModelsResponse","typescript":"listModels(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListModelsRequestSchema\u003e): Promise\u003cListModelsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/models\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListModelsRequest{}\n\n\tresp, err := client.Admin().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/admin/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.admin.v1 import admin_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 = admin_pb2.ListModelsRequest()\ntry:\n    result = client.admin.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.admin.listModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/models","slug":"list-models"}

Get model

Request fields:

FieldRequiredDescription
model_idnoCatalog entry UUID to fetch.

Response fields:

FieldRequiredDescription
modelnoThe requested model.
{"signatures":{"go":"func (x *AdminClient) GetModel(ctx context.Context, req *adminv1.GetModelRequest) (*adminv1.GetModelResponse, error)","python":"get_model(req: admin_pb2.GetModelRequest) -\u003e GetModelResponse","typescript":"getModel(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetModelRequestSchema\u003e): Promise\u003cGetModelResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/models/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetModelRequest{}\n\n\tresp, err := client.Admin().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/admin/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.admin.v1 import admin_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 = admin_pb2.GetModelRequest()\ntry:\n    result = client.admin.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.admin.getModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/models/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/models/{model_id}","slug":"get-model"}

Get model usage

Changed in v0.8.0 (new features): Admins can see which models their organization uses retire soon, and which projects and API keys still call them. A model whose retirement date has passed is included, flagged as retired, while the organization still calls it. Results cover only your organization.

What it does: Lists the projects and API keys in the caller's organization that called a catalogue model inside a bounded window, and when each was last seen (fraser#10229). Organization-scoped, never platform-wide: a caller with no organization binding is denied, and a project-tier key sees only its own project.

Request fields:

FieldRequiredDescription
model_idnoCatalog entry UUID (ai_models id) to report usage for.
window_daysnoLook-back window in whole UTC days (plus today). Defaults to 30 when unset; must be between 1 and 365.

Response fields:

FieldRequiredDescription
model_idnoEcho of the requested model.
window_daysnoThe effective window, after defaulting.
projectsnoProjects that called the model, most recently seen first.
api_keysnoAPI keys that called the model, most recently seen first.
{"signatures":{"go":"func (x *AdminClient) GetModelUsage(ctx context.Context, req *adminv1.GetModelUsageRequest) (*adminv1.GetModelUsageResponse, error)","python":"get_model_usage(req: admin_pb2.GetModelUsageRequest) -\u003e GetModelUsageResponse","typescript":"getModelUsage(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetModelUsageRequestSchema\u003e): Promise\u003cGetModelUsageResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/models/01H.../usage\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetModelUsageRequest{}\n\n\tresp, err := client.Admin().GetModelUsage(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/admin/getmodelusage\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.admin.v1 import admin_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 = admin_pb2.GetModelUsageRequest()\ntry:\n    result = client.admin.get_model_usage(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.admin.getModelUsage(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/models/01H.../usage\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/models/{model_id}/usage","slug":"get-model-usage"}

List retiring models

Changed in v0.8.0 (new features): Admins can see which models their organization uses retire soon, and which projects and API keys still call them. A model whose retirement date has passed is included, flagged as retired, while the organization still calls it. Results cover only your organization.

What it does: Lists the catalogue models the caller's organization is actually using (called in the last 30 days) whose retirement_date is inside the requested window (fraser#10229). Computed server-side from the catalogue lifecycle verdict and the usage rollups. Organization-scoped, never platform-wide.

Request fields:

FieldRequiredDescription
window_daysnoLook-ahead window in days from today for metadata.retirement_date. Defaults to 60 when unset; must be between 1 and 365.

Response fields:

FieldRequiredDescription
window_daysnoThe effective retirement window, after defaulting.
usage_window_daysnoThe usage window that defines "in use" (30 days).
modelsnoModels in use that retire inside the window, soonest first.
{"signatures":{"go":"func (x *AdminClient) ListRetiringModels(ctx context.Context, req *adminv1.ListRetiringModelsRequest) (*adminv1.ListRetiringModelsResponse, error)","python":"list_retiring_models(req: admin_pb2.ListRetiringModelsRequest) -\u003e ListRetiringModelsResponse","typescript":"listRetiringModels(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListRetiringModelsRequestSchema\u003e): Promise\u003cListRetiringModelsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/retiring-models\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListRetiringModelsRequest{}\n\n\tresp, err := client.Admin().ListRetiringModels(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/admin/listretiringmodels\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.admin.v1 import admin_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 = admin_pb2.ListRetiringModelsRequest()\ntry:\n    result = client.admin.list_retiring_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.admin.listRetiringModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/retiring-models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/retiring-models","slug":"list-retiring-models"}

List catalog providers

Changed in v0.6.0 (new features): Provider reads have a new field, has_credential: true when the provider's platform key is stored, false when it is not, and unset when the check could not run (the read still succeeds). ListProviders and GetProvider also accept a customer_id, and optionally a project_id within it, which returns the same providers without the key suffix or internal metadata.

Request fields:

FieldRequiredDescription
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 re-proposes every disabled row as new on each run -- and, with disable-absent enabled, would act on that. The store has always supported this (catalog.Store.ListProviders takes includeDisabled); only the admin surface could not ask for it.

Response fields:

FieldRequiredDescription
providersnoProviders in catalog order: enabled ones only, or the whole catalogue when the request set include_disabled.
{"signatures":{"go":"func (x *AdminClient) ListCatalogProviders(ctx context.Context, req *adminv1.ListCatalogProvidersRequest) (*adminv1.ListCatalogProvidersResponse, error)","python":"list_catalog_providers(req: admin_pb2.ListCatalogProvidersRequest) -\u003e ListCatalogProvidersResponse","typescript":"listCatalogProviders(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListCatalogProvidersRequestSchema\u003e): Promise\u003cListCatalogProvidersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListCatalogProvidersRequest{}\n\n\tresp, err := client.Admin().ListCatalogProviders(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/admin/listcatalogproviders\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.admin.v1 import admin_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 = admin_pb2.ListCatalogProvidersRequest()\ntry:\n    result = client.admin.list_catalog_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.admin.listCatalogProviders(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/providers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/catalog/providers","slug":"list-catalog-providers"}

List catalog models

Changed in v0.7.0 (new features): Catalog model lists can be paged with page, and support search, mode, modality, context-window and price filters, sorting and snapshot grouping. Paged lists leave out models whose provider is disabled unless include_disabled is set.

Changed in v0.7.0 (deprecations): A catalog model list that sets only provider_id or include_disabled still returns the full catalog, but is deprecated and will return one page in a later release. Setting any other field returns one page.

Request fields:

FieldRequiredDescription
provider_idnoFilter to models belonging to this provider. Empty includes all providers.
include_disablednoInclude disabled models. Paginated reads otherwise also leave out models belonging to disabled providers; the unpaginated response does not.
pagenoPagination. A request that sets none of the fields below keeps the deprecated unpaginated response: every matching model, ordered by provider then model. That response is deprecated and will be removed; send page and follow page.next_page_token. Page size defaults to 20 items when page is set; maximum size 5000. order_by supports name, context_window, input_price, output_price (asc/desc). Empty order_by prioritizes first-party providers, release date descending, then model name. page.filter is unsupported; use the typed fields below.
searchnoOrdered, case-insensitive search across model and provider names/labels.
modenoundocumented
input_modalitynoundocumented
output_modalitynoundocumented
model_idsnoAdditional selection, not an authorization grant. Empty ids selects no models.
context_windownoundocumented
input_pricenoundocumented
output_pricenoundocumented
group_snapshotsnoCount a base model and its snapshots as one item, before pagination.
skipnoSkip items for numbered-page navigation. Cannot be combined with page_token.

Response fields:

FieldRequiredDescription
modelsnoFlat results; for grouped requests use groups instead.
pagenoundocumented
groupsnoundocumented
total_countnoFiltered model count, or group/standalone count when group_snapshots is set.
{"signatures":{"go":"func (x *AdminClient) ListCatalogModels(ctx context.Context, req *adminv1.ListCatalogModelsRequest) (*adminv1.ListCatalogModelsResponse, error)","python":"list_catalog_models(req: admin_pb2.ListCatalogModelsRequest) -\u003e ListCatalogModelsResponse","typescript":"listCatalogModels(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListCatalogModelsRequestSchema\u003e): Promise\u003cListCatalogModelsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListCatalogModelsRequest{}\n\n\tresp, err := client.Admin().ListCatalogModels(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/admin/listcatalogmodels\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.admin.v1 import admin_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 = admin_pb2.ListCatalogModelsRequest()\ntry:\n    result = client.admin.list_catalog_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.admin.listCatalogModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/catalog/models","slug":"list-catalog-models"}

List mcp catalog servers

Request fields:

FieldRequiredDescription
include_disablednoWhen true, include is_enabled=false entries.

Response fields:

FieldRequiredDescription
serversnoundocumented
{"signatures":{"go":"func (x *AdminClient) ListMcpCatalogServers(ctx context.Context, req *adminv1.ListMcpCatalogServersRequest) (*adminv1.ListMcpCatalogServersResponse, error)","python":"list_mcp_catalog_servers(req: admin_pb2.ListMcpCatalogServersRequest) -\u003e ListMcpCatalogServersResponse","typescript":"listMcpCatalogServers(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListMcpCatalogServersRequestSchema\u003e): Promise\u003cListMcpCatalogServersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/mcp/catalog/servers\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListMcpCatalogServersRequest{}\n\n\tresp, err := client.Admin().ListMcpCatalogServers(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/admin/listmcpcatalogservers\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.admin.v1 import admin_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 = admin_pb2.ListMcpCatalogServersRequest()\ntry:\n    result = client.admin.list_mcp_catalog_servers(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.admin.listMcpCatalogServers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/mcp/catalog/servers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/mcp/catalog/servers","slug":"list-mcp-catalog-servers"}

Upsert catalog provider

Changed in v0.6.0 (new features): CreateProvider adds a provider and returns AlreadyExists if the id is taken, and DeleteProviderCredential removes a provider's platform key. UpsertProvider now needs display_name, base_url and a canonical id only when it creates the provider, so {id, is_enabled} toggles an existing one.

Changed in v0.6.0 (new features): UpsertProvider has a new field, remove_metadata_keys, that removes the named top-level keys from the provider's metadata. A null value in metadata is still stored as sent. credential and credential_suffix cannot be removed this way.

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.

What it does: Admin-key catalog WRITES (fraser#8451). The identity-authenticated CatalogService.UpsertProvider/UpsertModel are mounted on the IA mux, which accepts only a session token or an <address>.<body> public.api_keys key -- so a platform admin_api_keys key can never reach them. That is the same wall #6025 hit for READS, solved the same way: expose the operation behind the admin auth path. These delegate to catalog.Server, so validation, metadata handling, suppress_route_regen semantics and the per-gateway fan-out are the SAME code as the identity surface rather than a parallel implementation. The motivating caller is the catalog-sync CronJob, whose only credential on a provisioned management plane is that plane's admin key.

Request fields:

FieldRequiredDescription
providernoThe provider to create or update. Reuses the identity surface's message so the two paths cannot drift in what a provider IS.

Response fields:

FieldRequiredDescription
providernoundocumented
{"signatures":{"go":"func (x *AdminClient) UpsertCatalogProvider(ctx context.Context, req *adminv1.UpsertCatalogProviderRequest) (*adminv1.UpsertCatalogProviderResponse, error)","python":"upsert_catalog_provider(req: admin_pb2.UpsertCatalogProviderRequest) -\u003e UpsertCatalogProviderResponse","typescript":"upsertCatalogProvider(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpsertCatalogProviderRequestSchema\u003e): Promise\u003cUpsertCatalogProviderResponse\u003e","curl":"curl -X PUT \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpsertCatalogProviderRequest{}\n\n\tresp, err := client.Admin().UpsertCatalogProvider(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/admin/upsertcatalogprovider\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.admin.v1 import admin_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 = admin_pb2.UpsertCatalogProviderRequest()\ntry:\n    result = client.admin.upsert_catalog_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.admin.upsertCatalogProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PUT \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/providers/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider\": {}\n  }'"},"persona":"Admin","httpVerb":"PUT","httpPath":"/admin/v1/catalog/providers/{provider.id}","slug":"upsert-catalog-provider"}

Upsert catalog model

Changed in v0.10.0 (new features): UpsertModel takes clear_fields, to clear stored values such as a price, the context window or the backend URLs, and remove_metadata_keys, to remove metadata keys. A request that sets neither works as before.

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.

Request fields:

FieldRequiredDescription
modelnoSee UpsertCatalogProviderRequest.provider.

Response fields:

FieldRequiredDescription
modelnoundocumented
{"signatures":{"go":"func (x *AdminClient) UpsertCatalogModel(ctx context.Context, req *adminv1.UpsertCatalogModelRequest) (*adminv1.UpsertCatalogModelResponse, error)","python":"upsert_catalog_model(req: admin_pb2.UpsertCatalogModelRequest) -\u003e UpsertCatalogModelResponse","typescript":"upsertCatalogModel(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpsertCatalogModelRequestSchema\u003e): Promise\u003cUpsertCatalogModelResponse\u003e","curl":"curl -X PUT \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpsertCatalogModelRequest{}\n\n\tresp, err := client.Admin().UpsertCatalogModel(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/admin/upsertcatalogmodel\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.admin.v1 import admin_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 = admin_pb2.UpsertCatalogModelRequest()\ntry:\n    result = client.admin.upsert_catalog_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.admin.upsertCatalogModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PUT \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": {}\n  }'"},"persona":"Admin","httpVerb":"PUT","httpPath":"/admin/v1/catalog/models","slug":"upsert-catalog-model"}

Regenerate catalog routes

What it does: Publish the catalogue to the data plane: one GLOBAL_ROUTES regeneration. The counterpart to suppress_route_regen on the two upserts above. A batch caller suppresses per-write regeneration and calls this ONCE at the end, so ~700 entries cost one fan-out rather than ~700. Deliberately takes NO caller-supplied scope. The underlying trigger must carry the "system" sentinel or the configurator narrows delivery to the caller's own customer, stranding every other workspace on the previous catalogue -- and the catalogue is global (ai_providers is keyed by name, ai_models is not customer-scoped). Server-side only, so a caller cannot get that wrong.

Request fields:

FieldRequiredDescription
reasonnoFree-text note recorded in the regeneration log line, e.g. "catalog-sync 2026-09-09". Optional; no effect on what is regenerated.

Response fields:

FieldRequiredDescription
regeneratednoFalse when no route regenerator is wired (a management plane running without a configurator). The call is not an error in that case -- there is simply nothing to publish through -- but a caller that wrote entries needs to know they are committed and unpublished.
{"signatures":{"go":"func (x *AdminClient) RegenerateCatalogRoutes(ctx context.Context, req *adminv1.RegenerateCatalogRoutesRequest) (*adminv1.RegenerateCatalogRoutesResponse, error)","python":"regenerate_catalog_routes(req: admin_pb2.RegenerateCatalogRoutesRequest) -\u003e RegenerateCatalogRoutesResponse","typescript":"regenerateCatalogRoutes(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RegenerateCatalogRoutesRequestSchema\u003e): Promise\u003cRegenerateCatalogRoutesResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/catalog:regenerate-routes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RegenerateCatalogRoutesRequest{}\n\n\tresp, err := client.Admin().RegenerateCatalogRoutes(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/admin/regeneratecatalogroutes\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.admin.v1 import admin_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 = admin_pb2.RegenerateCatalogRoutesRequest()\ntry:\n    result = client.admin.regenerate_catalog_routes(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.admin.regenerateCatalogRoutes(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog:regenerate-routes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/catalog:regenerate-routes","slug":"regenerate-catalog-routes"}

Record catalog sync

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: Catalog sync freshness (fraser#7951), admin-key half. Same wall, same shape as the writes above: the catalog-sync CronJob's only credential on a provisioned management plane is that plane's admin key, which cannot reach tars.catalog.v1.CatalogService at all. Both routes delegate to the same catalog.Server, so there is one record and one set of merge rules whichever surface wrote it -- a hand-run with a session token and a nightly job with an admin key update the same row. Two records would be worse than none: each would look stale whenever the other ran.

Request fields:

FieldRequiredDescription
runnoThe run to record. Reuses the identity surface's message so the two paths cannot drift in what a sync run IS, and so the merge rules documented on CatalogService.RecordCatalogSync are the only ones.

Response fields:

FieldRequiredDescription
statenoThe merged record as persisted. Never null.
{"signatures":{"go":"func (x *AdminClient) RecordCatalogSync(ctx context.Context, req *adminv1.RecordCatalogSyncRequest) (*adminv1.RecordCatalogSyncResponse, error)","python":"record_catalog_sync(req: admin_pb2.RecordCatalogSyncRequest) -\u003e RecordCatalogSyncResponse","typescript":"recordCatalogSync(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RecordCatalogSyncRequestSchema\u003e): Promise\u003cRecordCatalogSyncResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"run\": {}\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RecordCatalogSyncRequest{}\n\n\tresp, err := client.Admin().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/admin/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.admin.v1 import admin_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 = admin_pb2.RecordCatalogSyncRequest()\ntry:\n    result = client.admin.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.admin.recordCatalogSync(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"run\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/catalog/sync-state","slug":"record-catalog-sync"}

Get 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.

Request body: None.

Response fields:

FieldRequiredDescription
statenoNever null; both timestamps unset means no sync has ever been recorded.
{"signatures":{"go":"func (x *AdminClient) GetCatalogSyncState(ctx context.Context, req *adminv1.GetCatalogSyncStateRequest) (*adminv1.GetCatalogSyncStateResponse, error)","python":"get_catalog_sync_state(req: admin_pb2.GetCatalogSyncStateRequest) -\u003e GetCatalogSyncStateResponse","typescript":"getCatalogSyncState(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetCatalogSyncStateRequestSchema\u003e): Promise\u003cGetCatalogSyncStateResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetCatalogSyncStateRequest{}\n\n\tresp, err := client.Admin().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/admin/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.admin.v1 import admin_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 = admin_pb2.GetCatalogSyncStateRequest()\ntry:\n    result = client.admin.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.admin.getCatalogSyncState(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/sync-state\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/catalog/sync-state","slug":"get-catalog-sync-state"}

Plan catalog sync

Changed in v0.8.0 (new features): The model catalog can be synced through the admin API: preview what a sync would change, apply it in the background pinned to the exact documents previewed, and poll the run's progress. One sync runs at a time.

What it does: Fetches the published catalogue and returns what a sync would do, writing nothing to the catalogue itself. It DOES advance the sync-state record's checked_* fields, exactly as a CLI dry run does -- that record is what a dashboard's "new models available" indicator reads, and a preview is precisely "this plane checked the published catalogue". Hence models:EDIT rather than READ: the RPC writes the same record RecordCatalogSync writes, so it carries the same atom.

Request body: None.

Response fields:

FieldRequiredDescription
catalog_versionnoThe published catalogue's exportedAt, verbatim; may be empty.
sourcesnoThe documents this plan read, with their sha256 digests. Feed these back on ApplyCatalogSync so the apply is pinned to what was reviewed.
providersnoOnly entries that would change; unchanged entries are counted below.
modelsnoundocumented
skippednoundocumented
absentnoundocumented
stagednoundocumented
unknown_providersnoProviders the published models reference that exist neither in the published providers document nor on this plane. Their models are in skipped; this is the summary by name.
warningsnoCuration inconsistencies in the published documents. Never fatal.
writesnoHow many entries an apply would write: len(providers)+len(models) above.
unchanged_providersnoundocumented
unchanged_modelsnoundocumented
statenoThe sync-state record AFTER this plan recorded its checked_* fields. Returned so a dashboard refreshes its staleness indicator without a second round-trip. Never null.
{"signatures":{"go":"func (x *AdminClient) PlanCatalogSync(ctx context.Context, req *adminv1.PlanCatalogSyncRequest) (*adminv1.PlanCatalogSyncResponse, error)","python":"plan_catalog_sync(req: admin_pb2.PlanCatalogSyncRequest) -\u003e PlanCatalogSyncResponse","typescript":"planCatalogSync(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.PlanCatalogSyncRequestSchema\u003e): Promise\u003cPlanCatalogSyncResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/sync:plan\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.PlanCatalogSyncRequest{}\n\n\tresp, err := client.Admin().PlanCatalogSync(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/admin/plancatalogsync\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.admin.v1 import admin_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 = admin_pb2.PlanCatalogSyncRequest()\ntry:\n    result = client.admin.plan_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.admin.planCatalogSync(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/sync:plan\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/catalog/sync:plan","slug":"plan-catalog-sync"}

Apply catalog sync

Changed in v0.8.0 (new features): The model catalog can be synced through the admin API: preview what a sync would change, apply it in the background pinned to the exact documents previewed, and poll the run's progress. One sync runs at a time.

What it does: Starts one background sync run and returns it RUNNING; poll GetCatalogSyncRun for progress. At most one run exists at a time -- a second apply while one is in flight fails with ALREADY_EXISTS. The request MUST carry the sources (with sha256 digests) the preview reported. The apply re-fetches pinned to those digests, so what gets applied is byte-for-byte what the human reviewed; a published catalogue that changed in between fails the run with an instruction to re-preview rather than silently applying something nobody looked at. Error-code contract, which a dashboard branches on (never on message text): - ABORTED: the preview went stale -- the source configuration changed under the reviewed pin set. Re-run PlanCatalogSync and apply again. The same verdict reached asynchronously (the published catalogue changed between preview and apply) surfaces as a FAILED run with failure_reason = STALE_CATALOG. - FAILED_PRECONDITION: the plane cannot sync until an operator fixes something (sources unconfigured, published catalogue malformed). Retrying as-is will not help. - ALREADY_EXISTS: a run is in flight; poll it. - INVALID_ARGUMENT: the request is missing the preview's sources. All-or-nothing by design: no per-entry selection, and no disable-absent. The published catalogue is a curated SUBSET of what a plane may legitimately hold (vertex and vertexanthropic models are seeded but not published), so a one-click disable-absent would silently turn off models customers are routing to. The plan lists absent models read-only instead.

Request fields:

FieldRequiredDescription
expected_catalog_versionnoThe preview's catalog_version, verbatim (may be empty, as the envelope field is optional). A cheap first check before the digest comparison.
expected_sourcesnoThe preview's sources, REQUIRED, matched against the configured source set by display name. Each sha256 pins the apply's re-fetch of that document; any mismatch fails the run before anything is written.

Response fields:

FieldRequiredDescription
runnoThe run just started, phase RUNNING. Poll GetCatalogSyncRun.
{"signatures":{"go":"func (x *AdminClient) ApplyCatalogSync(ctx context.Context, req *adminv1.ApplyCatalogSyncRequest) (*adminv1.ApplyCatalogSyncResponse, error)","python":"apply_catalog_sync(req: admin_pb2.ApplyCatalogSyncRequest) -\u003e ApplyCatalogSyncResponse","typescript":"applyCatalogSync(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ApplyCatalogSyncRequestSchema\u003e): Promise\u003cApplyCatalogSyncResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/sync:apply\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"expected_catalog_version\": \"...\",\n    \"expected_sources\": []\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ApplyCatalogSyncRequest{}\n\n\tresp, err := client.Admin().ApplyCatalogSync(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/admin/applycatalogsync\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.admin.v1 import admin_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 = admin_pb2.ApplyCatalogSyncRequest()\ntry:\n    result = client.admin.apply_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.admin.applyCatalogSync(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/sync:apply\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"expected_catalog_version\": \"...\",\n    \"expected_sources\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/catalog/sync:apply","slug":"apply-catalog-sync"}

Get catalog sync run

Changed in v0.8.0 (new features): The model catalog can be synced through the admin API: preview what a sync would change, apply it in the background pinned to the exact documents previewed, and poll the run's progress. One sync runs at a time.

What it does: Returns the most recent apply run, running or finished. An unset run means no apply has ever been started on this plane.

Request body: None.

Response fields:

FieldRequiredDescription
runnoUnset when no apply has ever been started on this plane.
{"signatures":{"go":"func (x *AdminClient) GetCatalogSyncRun(ctx context.Context, req *adminv1.GetCatalogSyncRunRequest) (*adminv1.GetCatalogSyncRunResponse, error)","python":"get_catalog_sync_run(req: admin_pb2.GetCatalogSyncRunRequest) -\u003e GetCatalogSyncRunResponse","typescript":"getCatalogSyncRun(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetCatalogSyncRunRequestSchema\u003e): Promise\u003cGetCatalogSyncRunResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/catalog/sync/run\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetCatalogSyncRunRequest{}\n\n\tresp, err := client.Admin().GetCatalogSyncRun(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/admin/getcatalogsyncrun\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.admin.v1 import admin_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 = admin_pb2.GetCatalogSyncRunRequest()\ntry:\n    result = client.admin.get_catalog_sync_run(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.admin.getCatalogSyncRun(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog/sync/run\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/catalog/sync/run","slug":"get-catalog-sync-run"}

Get model lifecycles

Changed in v0.8.0 (new features): Admins can read whether a model in the catalog is retired, deprecated, new or in preview, with the reason and any retirement date. A model the catalog does not contain is left out of the result.

What it does: Lifecycle verdicts (retired / deprecated / new / preview) for a batch of catalogue models, keyed by model id (fraser#10228). The verdict is computed by catalogsync.LifecycleOfModel -- the function the catalog sync itself acts on -- so a consumer badges a model with the same answer the sync reached, rather than re-deriving it from metadata and drifting. Batch-by-id rather than a field on Model because the Admin Console lists models from its own ai_models query, not from this service: it already holds the ids and needs only the verdicts. An id that matches no catalogue row is ABSENT from the response map, never present with a zero verdict: a zero verdict means "no lifecycle signal" and would render as a normal live model. Disabled models are included -- a retired model is usually disabled, and that is exactly the one to badge.

Request fields:

FieldRequiredDescription
model_idsnoCatalogue model ids (ai_models.id). Duplicates are allowed and collapse to one map entry. Empty returns an empty map. max_items 1000: the whole current catalogue (~700 models) fits in one call with headroom, so the Console never has to batch a full listing, while staying well under the catalogue store's 5000-row page cap, so one request is always answered by one bounded read.

Response fields:

FieldRequiredDescription
lifecyclesnoVerdict per requested model id that exists in the catalogue. Ids with no catalogue row are absent, not zero-valued -- see GetModelLifecycles.
{"signatures":{"go":"func (x *AdminClient) GetModelLifecycles(ctx context.Context, req *adminv1.GetModelLifecyclesRequest) (*adminv1.GetModelLifecyclesResponse, error)","python":"get_model_lifecycles(req: admin_pb2.GetModelLifecyclesRequest) -\u003e GetModelLifecyclesResponse","typescript":"getModelLifecycles(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetModelLifecyclesRequestSchema\u003e): Promise\u003cGetModelLifecyclesResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/catalog:model-lifecycles\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model_ids\": []\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetModelLifecyclesRequest{}\n\n\tresp, err := client.Admin().GetModelLifecycles(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/admin/getmodellifecycles\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.admin.v1 import admin_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 = admin_pb2.GetModelLifecyclesRequest()\ntry:\n    result = client.admin.get_model_lifecycles(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.admin.getModelLifecycles(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/catalog:model-lifecycles\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model_ids\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/catalog:model-lifecycles","slug":"get-model-lifecycles"}

Add project model

Changed in v0.8.0 (bug fixes): Adding or removing a model from a project now updates keys that carry their own settings (BYOK, fallback, traffic split, or a rate limit), so they no longer keep routing against the old model list. A key created with CreateApiKey or IssueMyKey now gets its own routes instead of waiting on an unrelated change. Both updates are sent in the background, so the call returns without waiting for them.

Deprecated Use CatalogService.AssignModelToProject instead.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to assign the model to.
model_idnoCatalog model UUID to assign.

Response fields:

FieldRequiredDescription
entrynoThe created model assignment.
{"signatures":{"go":"func (x *AdminClient) AddProjectModel(ctx context.Context, req *adminv1.AddProjectModelRequest) (*adminv1.AddProjectModelResponse, error)","python":"add_project_model(req: admin_pb2.AddProjectModelRequest) -\u003e AddProjectModelResponse","typescript":"addProjectModel(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AddProjectModelRequestSchema\u003e): Promise\u003cAddProjectModelResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AddProjectModelRequest{}\n\n\tresp, err := client.Admin().AddProjectModel(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/admin/addprojectmodel\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.admin.v1 import admin_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 = admin_pb2.AddProjectModelRequest()\ntry:\n    result = client.admin.add_project_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.admin.addProjectModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model_id\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/models","slug":"add-project-model"}

List project models

Deprecated Use CatalogService.ListProjectModels instead.

no scope on catalog side; assign/unassign require project_owner

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose assigned models to list.

Response fields:

FieldRequiredDescription
entriesnoModels assigned to the project.
{"signatures":{"go":"func (x *AdminClient) ListProjectModels(ctx context.Context, req *adminv1.ListProjectModelsRequest) (*adminv1.ListProjectModelsResponse, error)","python":"list_project_models(req: admin_pb2.ListProjectModelsRequest) -\u003e ListProjectModelsResponse","typescript":"listProjectModels(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectModelsRequestSchema\u003e): Promise\u003cListProjectModelsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectModelsRequest{}\n\n\tresp, err := client.Admin().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/admin/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.admin.v1 import admin_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 = admin_pb2.ListProjectModelsRequest()\ntry:\n    result = client.admin.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.admin.listProjectModels(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../models\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/models","slug":"list-project-models"}

Remove project model

Changed in v0.8.0 (bug fixes): Adding or removing a model from a project now updates keys that carry their own settings (BYOK, fallback, traffic split, or a rate limit), so they no longer keep routing against the old model list. A key created with CreateApiKey or IssueMyKey now gets its own routes instead of waiting on an unrelated change. Both updates are sent in the background, so the call returns without waiting for them.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to remove the model from.
model_idnoCatalog model UUID to unassign.

Response fields:

FieldRequiredDescription
successnoTrue if the assignment was removed.
{"signatures":{"go":"func (x *AdminClient) RemoveProjectModel(ctx context.Context, req *adminv1.RemoveProjectModelRequest) (*adminv1.RemoveProjectModelResponse, error)","python":"remove_project_model(req: admin_pb2.RemoveProjectModelRequest) -\u003e RemoveProjectModelResponse","typescript":"removeProjectModel(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RemoveProjectModelRequestSchema\u003e): Promise\u003cRemoveProjectModelResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../models/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RemoveProjectModelRequest{}\n\n\tresp, err := client.Admin().RemoveProjectModel(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/admin/removeprojectmodel\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.admin.v1 import admin_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 = admin_pb2.RemoveProjectModelRequest()\ntry:\n    result = client.admin.remove_project_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.admin.removeProjectModel(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../models/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/models/{model_id}","slug":"remove-project-model"}

Add project provider

Changed in v0.11.0 (bug fixes): A request with a NUL character in a name, description or filter field now returns 400 invalid_argument. It returned 500 internal before, which clients retry and which counted as a server failure. This applies when the management plane uses the extended query protocol, which is the default. A deployment that sets global.useSimpleProtocol (USE_QUERY_EXEC_MODE_SIMPLE_PROTOCOL=true, used with pgbouncer) still returns 500 for these requests.

Changed in v0.9.0 (behaviour changes): Adding or removing a provider on a project's allow-list through the API now needs the project provider permission, which Project Owner and Super Admin hold, as the Admin Console already did. Provider Admin and Model Admin no longer give it, and neither does a custom role with only the providers permissions.

Changed in v0.9.0 (new features): Project admins can add and remove the providers on their own project's allow-list.

What it does: Adds a provider to the project's allow-list. A project admin may call it for their own project.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to enable the provider for.
provider_namenoProvider name to enable (e.g. "openai").

Response fields:

FieldRequiredDescription
entrynoThe created provider assignment.
{"signatures":{"go":"func (x *AdminClient) AddProjectProvider(ctx context.Context, req *adminv1.AddProjectProviderRequest) (*adminv1.AddProjectProviderResponse, error)","python":"add_project_provider(req: admin_pb2.AddProjectProviderRequest) -\u003e AddProjectProviderResponse","typescript":"addProjectProvider(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AddProjectProviderRequestSchema\u003e): Promise\u003cAddProjectProviderResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_name\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AddProjectProviderRequest{}\n\n\tresp, err := client.Admin().AddProjectProvider(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/admin/addprojectprovider\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.admin.v1 import admin_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 = admin_pb2.AddProjectProviderRequest()\ntry:\n    result = client.admin.add_project_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.admin.addProjectProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_name\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/providers","slug":"add-project-provider"}

List project providers

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose enabled providers to list.

Response fields:

FieldRequiredDescription
entriesnoProviders enabled for the project.
{"signatures":{"go":"func (x *AdminClient) ListProjectProviders(ctx context.Context, req *adminv1.ListProjectProvidersRequest) (*adminv1.ListProjectProvidersResponse, error)","python":"list_project_providers(req: admin_pb2.ListProjectProvidersRequest) -\u003e ListProjectProvidersResponse","typescript":"listProjectProviders(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectProvidersRequestSchema\u003e): Promise\u003cListProjectProvidersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectProvidersRequest{}\n\n\tresp, err := client.Admin().ListProjectProviders(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/admin/listprojectproviders\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.admin.v1 import admin_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 = admin_pb2.ListProjectProvidersRequest()\ntry:\n    result = client.admin.list_project_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.admin.listProjectProviders(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/providers","slug":"list-project-providers"}

Remove project provider

Changed in v0.9.0 (behaviour changes): Removing a provider from a project's allow-list fails with FAILED_PRECONDITION while the project still has models from that provider.

Changed in v0.9.0 (behaviour changes): Adding or removing a provider on a project's allow-list through the API now needs the project provider permission, which Project Owner and Super Admin hold, as the Admin Console already did. Provider Admin and Model Admin no longer give it, and neither does a custom role with only the providers permissions.

Changed in v0.9.0 (new features): Project admins can add and remove the providers on their own project's allow-list.

What it does: Removes a provider from the project's allow-list. Fails FAILED_PRECONDITION while the project still has models from that provider: unassign them first. A project admin may call it for their own project.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to disable the provider for.
provider_namenoProvider name to disable.

Response fields:

FieldRequiredDescription
successnoTrue if the provider was removed.
{"signatures":{"go":"func (x *AdminClient) RemoveProjectProvider(ctx context.Context, req *adminv1.RemoveProjectProviderRequest) (*adminv1.RemoveProjectProviderResponse, error)","python":"remove_project_provider(req: admin_pb2.RemoveProjectProviderRequest) -\u003e RemoveProjectProviderResponse","typescript":"removeProjectProvider(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RemoveProjectProviderRequestSchema\u003e): Promise\u003cRemoveProjectProviderResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RemoveProjectProviderRequest{}\n\n\tresp, err := client.Admin().RemoveProjectProvider(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/admin/removeprojectprovider\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.admin.v1 import admin_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 = admin_pb2.RemoveProjectProviderRequest()\ntry:\n    result = client.admin.remove_project_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.admin.removeProjectProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../providers/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/providers/{provider_name}","slug":"remove-project-provider"}

Add project mcp server

Changed in v0.8.0 (behaviour changes): Listing, adding and removing a project's MCP servers now needs the project MCP permission. The MCP Admin role doesn't include it, so its holders need Project Owner or Super Admin for all three.

Changed in v0.8.0 (new features): Project owners can add and remove their project's MCP servers, and Viewers can list them. The list shows each server's name, description, icon, enabled state and last update, including servers disabled since, and can be paged, searched by name, filtered by enabled state and sorted.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to assign the MCP server to.
server_idnoCatalog server ID to assign (e.g. "github").

Response fields:

FieldRequiredDescription
entrynoThe created MCP server assignment.
{"signatures":{"go":"func (x *AdminClient) AddProjectMcpServer(ctx context.Context, req *adminv1.AddProjectMcpServerRequest) (*adminv1.AddProjectMcpServerResponse, error)","python":"add_project_mcp_server(req: admin_pb2.AddProjectMcpServerRequest) -\u003e AddProjectMcpServerResponse","typescript":"addProjectMcpServer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.AddProjectMcpServerRequestSchema\u003e): Promise\u003cAddProjectMcpServerResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"server_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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.AddProjectMcpServerRequest{}\n\n\tresp, err := client.Admin().AddProjectMcpServer(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/admin/addprojectmcpserver\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.admin.v1 import admin_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 = admin_pb2.AddProjectMcpServerRequest()\ntry:\n    result = client.admin.add_project_mcp_server(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.admin.addProjectMcpServer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"server_id\": \"...\"\n  }'"},"persona":"App Developer (API key)","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/mcp-servers","slug":"add-project-mcp-server"}

List project mcp servers

Changed in v0.11.0 (bug fixes): A request with a NUL character in a name, description or filter field now returns 400 invalid_argument. It returned 500 internal before, which clients retry and which counted as a server failure. This applies when the management plane uses the extended query protocol, which is the default. A deployment that sets global.useSimpleProtocol (USE_QUERY_EXEC_MODE_SIMPLE_PROTOCOL=true, used with pgbouncer) still returns 500 for these requests.

Changed in v0.8.0 (behaviour changes): Listing, adding and removing a project's MCP servers now needs the project MCP permission. The MCP Admin role doesn't include it, so its holders need Project Owner or Super Admin for all three.

Changed in v0.8.0 (new features): Project owners can add and remove their project's MCP servers, and Viewers can list them. The list shows each server's name, description, icon, enabled state and last update, including servers disabled since, and can be paged, searched by name, filtered by enabled state and sorted.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose assigned MCP servers to list.
pagenoPaging and order. order_by is one of server_id, name, updated_at or is_enabled, optionally followed by asc or desc; empty orders by server ID. Unset returns every server.
searchnoCase-insensitive substring match on the server name; empty matches all.
enablednoWhen set, only servers whose catalog entry has this enabled state.

Response fields:

FieldRequiredDescription
entriesnoMCP servers assigned to the project.
pagenoNext page cursor; unset when the request was unpaged or this is the last page.
totalnoServers matching search and enabled, across all pages.
{"signatures":{"go":"func (x *AdminClient) ListProjectMcpServers(ctx context.Context, req *adminv1.ListProjectMcpServersRequest) (*adminv1.ListProjectMcpServersResponse, error)","python":"list_project_mcp_servers(req: admin_pb2.ListProjectMcpServersRequest) -\u003e ListProjectMcpServersResponse","typescript":"listProjectMcpServers(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectMcpServersRequestSchema\u003e): Promise\u003cListProjectMcpServersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectMcpServersRequest{}\n\n\tresp, err := client.Admin().ListProjectMcpServers(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/admin/listprojectmcpservers\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.admin.v1 import admin_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 = admin_pb2.ListProjectMcpServersRequest()\ntry:\n    result = client.admin.list_project_mcp_servers(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.admin.listProjectMcpServers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/mcp-servers","slug":"list-project-mcp-servers"}

Remove project mcp server

Changed in v0.10.0 (security updates): Removing a catalog MCP server from a project now also detaches it from the legacy MCP profiles of users in the project, and editing the tools of a server that the project no longer grants is refused with PERMISSION_DENIED. Before, a legacy profile kept serving a server after its grant was removed.

Changed in v0.8.0 (behaviour changes): Listing, adding and removing a project's MCP servers now needs the project MCP permission. The MCP Admin role doesn't include it, so its holders need Project Owner or Super Admin for all three.

Changed in v0.8.0 (new features): Project owners can add and remove their project's MCP servers, and Viewers can list them. The list shows each server's name, description, icon, enabled state and last update, including servers disabled since, and can be paged, searched by name, filtered by enabled state and sorted.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to remove the MCP server from.
server_idnoCatalog server ID to remove.

Response fields:

FieldRequiredDescription
successnoTrue if the MCP server assignment was removed.
{"signatures":{"go":"func (x *AdminClient) RemoveProjectMcpServer(ctx context.Context, req *adminv1.RemoveProjectMcpServerRequest) (*adminv1.RemoveProjectMcpServerResponse, error)","python":"remove_project_mcp_server(req: admin_pb2.RemoveProjectMcpServerRequest) -\u003e RemoveProjectMcpServerResponse","typescript":"removeProjectMcpServer(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.RemoveProjectMcpServerRequestSchema\u003e): Promise\u003cRemoveProjectMcpServerResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.RemoveProjectMcpServerRequest{}\n\n\tresp, err := client.Admin().RemoveProjectMcpServer(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/admin/removeprojectmcpserver\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.admin.v1 import admin_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 = admin_pb2.RemoveProjectMcpServerRequest()\ntry:\n    result = client.admin.remove_project_mcp_server(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.admin.removeProjectMcpServer(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-servers/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/mcp-servers/{server_id}","slug":"remove-project-mcp-server"}

List project mcp server candidates

Changed in v0.8.0 (new features): Project owners can list the enabled MCP servers their project doesn't have yet, searched by name and paged, to pick which ones to add.

What it does: Returns enabled catalog servers not yet assigned to the project, ordered by name, for the add-server picker.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject the candidates are for.
searchnoCase-insensitive substring match on the server name; empty matches all.
page_sizenoMax servers per page (0 = server default of 50).
page_tokennoOpaque cursor from a previous response's next_page_token.

Response fields:

FieldRequiredDescription
candidatesnoPage of candidates, ordered by name then id.
next_page_tokennoCursor for the next page; empty when there are no more results.
{"signatures":{"go":"func (x *AdminClient) ListProjectMcpServerCandidates(ctx context.Context, req *adminv1.ListProjectMcpServerCandidatesRequest) (*adminv1.ListProjectMcpServerCandidatesResponse, error)","python":"list_project_mcp_server_candidates(req: admin_pb2.ListProjectMcpServerCandidatesRequest) -\u003e ListProjectMcpServerCandidatesResponse","typescript":"listProjectMcpServerCandidates(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectMcpServerCandidatesRequestSchema\u003e): Promise\u003cListProjectMcpServerCandidatesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-server-candidates\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectMcpServerCandidatesRequest{}\n\n\tresp, err := client.Admin().ListProjectMcpServerCandidates(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/admin/listprojectmcpservercandidates\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.admin.v1 import admin_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 = admin_pb2.ListProjectMcpServerCandidatesRequest()\ntry:\n    result = client.admin.list_project_mcp_server_candidates(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.admin.listProjectMcpServerCandidates(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp-server-candidates\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"App Developer (API key)","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/mcp-server-candidates","slug":"list-project-mcp-server-candidates"}

Trigger project mcp

What it does: (re)materializes the per-Project-Gateway MCP config for every gateway the (customer_id, project_id) is attached to. The dashboard MCP profile mutation path calls this after a profile create/update/delete so a freshly-created profile enters its project gateways' MCP_PROFILE config; without it the per-gateway config-gen never re-runs and /mcp/<profile> 404s on a strict-isolation gateway DP. Best-effort + dormant when the project has no gateways.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose gateways' MCP config to refresh.
{"signatures":{"go":"func (x *AdminClient) TriggerProjectMcp(ctx context.Context, req *adminv1.TriggerProjectMcpRequest) (*adminv1.TriggerProjectMcpResponse, error)","python":"trigger_project_mcp(req: admin_pb2.TriggerProjectMcpRequest) -\u003e TriggerProjectMcpResponse","typescript":"triggerProjectMcp(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.TriggerProjectMcpRequestSchema\u003e): Promise\u003cTriggerProjectMcpResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp:trigger\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.TriggerProjectMcpRequest{}\n\n\tresp, err := client.Admin().TriggerProjectMcp(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/admin/triggerprojectmcp\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.admin.v1 import admin_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 = admin_pb2.TriggerProjectMcpRequest()\ntry:\n    result = client.admin.trigger_project_mcp(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.admin.triggerProjectMcp(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../mcp:trigger\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/mcp:trigger","slug":"trigger-project-mcp"}

Get project settings

Changed in v0.8.0 (bug fixes): Getting, setting or deleting a project setting now returns NOT_FOUND when the project is missing or deleted. Deleting a project now deletes its settings, so a new project with the same name starts with none. The default project is still created on demand.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose settings to fetch.

Response fields:

FieldRequiredDescription
settingsnoAll settings for the project.
{"signatures":{"go":"func (x *AdminClient) GetProjectSettings(ctx context.Context, req *adminv1.GetProjectSettingsRequest) (*adminv1.GetProjectSettingsResponse, error)","python":"get_project_settings(req: admin_pb2.GetProjectSettingsRequest) -\u003e GetProjectSettingsResponse","typescript":"getProjectSettings(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetProjectSettingsRequestSchema\u003e): Promise\u003cGetProjectSettingsResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetProjectSettingsRequest{}\n\n\tresp, err := client.Admin().GetProjectSettings(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/admin/getprojectsettings\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.admin.v1 import admin_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 = admin_pb2.GetProjectSettingsRequest()\ntry:\n    result = client.admin.get_project_settings(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.admin.getProjectSettings(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/settings","slug":"get-project-settings"}

Upsert project setting

Changed in v0.8.0 (bug fixes): Getting, setting or deleting a project setting now returns NOT_FOUND when the project is missing or deleted. Deleting a project now deletes its settings, so a new project with the same name starts with none. The default project is still created on demand.

Changed in v0.8.0 (bug fixes): Project default settings, project membership changes, the request-log mode, and rate-limit policies moved to another target now reach your gateways within the usual update cycle. They were previously saved but not pushed, so keys kept an old rate limit or fallback, a removed member kept the project's shared provider keys, and a moved policy kept limiting its old keys. A project-wide rate limit is also now enforced on keys with no settings of their own.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to set the value on.
setting_namenoSetting key to create or update ("global-fallback" or "rate-limit").
setting_valuenoNew string-encoded value for the setting.

Response fields:

FieldRequiredDescription
settingnoThe created or updated setting.
{"signatures":{"go":"func (x *AdminClient) UpsertProjectSetting(ctx context.Context, req *adminv1.UpsertProjectSettingRequest) (*adminv1.UpsertProjectSettingResponse, error)","python":"upsert_project_setting(req: admin_pb2.UpsertProjectSettingRequest) -\u003e UpsertProjectSettingResponse","typescript":"upsertProjectSetting(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpsertProjectSettingRequestSchema\u003e): Promise\u003cUpsertProjectSettingResponse\u003e","curl":"curl -X PUT \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"setting_value\": \"...\"\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpsertProjectSettingRequest{}\n\n\tresp, err := client.Admin().UpsertProjectSetting(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/admin/upsertprojectsetting\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.admin.v1 import admin_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 = admin_pb2.UpsertProjectSettingRequest()\ntry:\n    result = client.admin.upsert_project_setting(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.admin.upsertProjectSetting(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PUT \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"setting_value\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"PUT","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/settings/{setting_name}","slug":"upsert-project-setting"}

Delete project setting

Changed in v0.8.0 (bug fixes): Getting, setting or deleting a project setting now returns NOT_FOUND when the project is missing or deleted. Deleting a project now deletes its settings, so a new project with the same name starts with none. The default project is still created on demand.

Changed in v0.8.0 (bug fixes): Project default settings, project membership changes, the request-log mode, and rate-limit policies moved to another target now reach your gateways within the usual update cycle. They were previously saved but not pushed, so keys kept an old rate limit or fallback, a removed member kept the project's shared provider keys, and a moved policy kept limiting its old keys. A project-wide rate limit is also now enforced on keys with no settings of their own.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to delete the setting from.
setting_namenoSetting key to delete ("global-fallback" or "rate-limit").

Response fields:

FieldRequiredDescription
successnoTrue if the setting was deleted.
{"signatures":{"go":"func (x *AdminClient) DeleteProjectSetting(ctx context.Context, req *adminv1.DeleteProjectSettingRequest) (*adminv1.DeleteProjectSettingResponse, error)","python":"delete_project_setting(req: admin_pb2.DeleteProjectSettingRequest) -\u003e DeleteProjectSettingResponse","typescript":"deleteProjectSetting(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteProjectSettingRequestSchema\u003e): Promise\u003cDeleteProjectSettingResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteProjectSettingRequest{}\n\n\tresp, err := client.Admin().DeleteProjectSetting(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/admin/deleteprojectsetting\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.admin.v1 import admin_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 = admin_pb2.DeleteProjectSettingRequest()\ntry:\n    result = client.admin.delete_project_setting(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.admin.deleteProjectSetting(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/settings/{setting_name}","slug":"delete-project-setting"}

Get project OIDC config

Changed in v0.10.0 (new features): A project's OIDC contract now names the token claim that identifies one caller, identity_claim, which is sub unless you name another, and how many callers the project may hold, principal_cap, which is 100 unless you set one at least 1. On a 0.10.0 data plane each caller gets its own API key, so budgets and rate limits apply per caller. The cap is enforced when a data plane resolves a contract caller. Existing contracts get both defaults. Omitting either field on a write keeps the stored value.

Changed in v0.7.0 (new features): A project can now publish an OIDC contract, naming the issuer that mints its tokens, the audience and scope they must carry and an optional entitlement. The issuer's discovery document is read as you write it, so an unreachable issuer is refused then. A contract naming an issuer and audience another organization's project already names is refused. A data plane on 0.7.0 or later admits callers against the contract; one below it answers them with a 401.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject whose OIDC contract to fetch.

Response fields:

FieldRequiredDescription
confignoThe project's contract. Absent when the project has none, which is the state every project starts in and the state in which it admits no OIDC caller.
{"signatures":{"go":"func (x *AdminClient) GetProjectOIDCConfig(ctx context.Context, req *adminv1.GetProjectOIDCConfigRequest) (*adminv1.GetProjectOIDCConfigResponse, error)","python":"get_project_oidc_config(req: admin_pb2.GetProjectOIDCConfigRequest) -\u003e GetProjectOIDCConfigResponse","typescript":"getProjectOIDCConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetProjectOIDCConfigRequestSchema\u003e): Promise\u003cGetProjectOIDCConfigResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetProjectOIDCConfigRequest{}\n\n\tresp, err := client.Admin().GetProjectOIDCConfig(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/admin/getprojectoidcconfig\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.admin.v1 import admin_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 = admin_pb2.GetProjectOIDCConfigRequest()\ntry:\n    result = client.admin.get_project_oidc_config(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.admin.getProjectOIDCConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/oidc","slug":"get-project-oidc-config"}

Upsert project OIDC config

Changed in v0.11.0 (security updates): A disabled project OIDC contract no longer reserves its issuer and audience, so another organization can enable a contract for that pair. Enabling a contract is still refused while another organization's enabled contract names the same issuer and audience, and the refusal now tells you to ask a platform administrator to release the pair. The refusal's audit entry names the holding organization and project, and the delete audit entry records the issuer and audience it released.

Changed in v0.11.0 (bug fixes): Changes that check a data plane's version, such as provider overrides, shared and catch-all hostnames, OIDC contracts and the newer rate-limit dimensions, no longer refuse a data plane on 0.11.0 or newer that was just upgraded or has had no configuration change for a day, because it now reports its version on every poll. A data plane silent for 24 hours is refused as down, disconnected or older than 0.11.0, with a prompt to check its connection and build.

Changed in v0.10.0 (behaviour changes): Writing a project's OIDC contract is refused on Agent Router Service (SaaS). Enabling a contract is refused while a data plane serving the project runs a build older than 0.10.0 or has not reported its build, and so is attaching a project whose contract is enabled to such a data plane. Each refusal names the data plane.

Changed in v0.10.0 (new features): A project's OIDC contract now names the token claim that identifies one caller, identity_claim, which is sub unless you name another, and how many callers the project may hold, principal_cap, which is 100 unless you set one at least 1. On a 0.10.0 data plane each caller gets its own API key, so budgets and rate limits apply per caller. The cap is enforced when a data plane resolves a contract caller. Existing contracts get both defaults. Omitting either field on a write keeps the stored value.

Changed in v0.7.0 (new features): A project can now publish an OIDC contract, naming the issuer that mints its tokens, the audience and scope they must carry and an optional entitlement. The issuer's discovery document is read as you write it, so an unreachable issuer is refused then. A contract naming an issuer and audience another organization's project already names is refused. A data plane on 0.7.0 or later admits callers against the contract; one below it answers them with a 401.

Changed in v0.7.0 (new features): The management plane refuses to fetch an OIDC issuer's discovery document from a non-public address: loopback, link-local, private, carrier-grade NAT, unique-local, unspecified, or another range reserved from public routing, such as benchmarking. It checks the address it connects to, redirects included, and the refusal names the setting that lifts it. A redirect is followed only to https on the issuer's own host and port.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to write the contract on.
issuernoThe identity provider that mints tokens for this project, e.g. "https://login.acmebank.com". Must be an absolute https URL, and the management plane fetches its discovery document to resolve the JWKS URI, so an issuer it cannot reach is refused here rather than at a caller's request.
audiencenoThe audience the token must carry, in practice the client ID of the customer's own application registration.
required_scopenoThe scope the token must carry, e.g. "ai.payments.use". One scope, so it carries no space.
required_entitlementnoThe entitlement the token must carry, e.g. the group the identity belongs to. Empty means the project requires none.
enablednoWhether the data plane admits OIDC callers to this project. Write false to refuse every OIDC caller while keeping the rest of the contract.
identity_claimnoThe token claim whose value identifies one caller. Omit it to keep the stored value, or "sub" on a new contract. Pick a claim the identity provider never reassigns: sub, or a client ID for a machine client. A mutable claim such as email hands one caller's key to whoever receives the value next.
principal_capnoHow many callers the project may hold. Omit it to keep the stored value, or 100 on a new contract. The value is at least 1, with no upper bound.

Response fields:

FieldRequiredDescription
confignoThe stored contract, carrying the JWKS URI the management plane resolved.
{"signatures":{"go":"func (x *AdminClient) UpsertProjectOIDCConfig(ctx context.Context, req *adminv1.UpsertProjectOIDCConfigRequest) (*adminv1.UpsertProjectOIDCConfigResponse, error)","python":"upsert_project_oidc_config(req: admin_pb2.UpsertProjectOIDCConfigRequest) -\u003e UpsertProjectOIDCConfigResponse","typescript":"upsertProjectOIDCConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpsertProjectOIDCConfigRequestSchema\u003e): Promise\u003cUpsertProjectOIDCConfigResponse\u003e","curl":"curl -X PUT \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"issuer\": \"...\",\n    \"audience\": \"...\",\n    \"required_scope\": \"...\",\n    \"required_entitlement\": \"...\",\n    \"enabled\": false,\n    \"identity_claim\": \"...\",\n    \"principal_cap\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpsertProjectOIDCConfigRequest{}\n\n\tresp, err := client.Admin().UpsertProjectOIDCConfig(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/admin/upsertprojectoidcconfig\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.admin.v1 import admin_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 = admin_pb2.UpsertProjectOIDCConfigRequest()\ntry:\n    result = client.admin.upsert_project_oidc_config(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.admin.upsertProjectOIDCConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PUT \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"issuer\": \"...\",\n    \"audience\": \"...\",\n    \"required_scope\": \"...\",\n    \"required_entitlement\": \"...\",\n    \"enabled\": false,\n    \"identity_claim\": \"...\",\n    \"principal_cap\": 0\n  }'"},"persona":"Admin","httpVerb":"PUT","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/oidc","slug":"upsert-project-oidc-config"}

Delete project OIDC config

Changed in v0.7.0 (new features): A project can now publish an OIDC contract, naming the issuer that mints its tokens, the audience and scope they must carry and an optional entitlement. The issuer's discovery document is read as you write it, so an unreachable issuer is refused then. A contract naming an issuer and audience another organization's project already names is refused. A data plane on 0.7.0 or later admits callers against the contract; one below it answers them with a 401.

Request fields:

FieldRequiredDescription
customer_idnoOwning customer slug.
project_idnoProject to remove the contract from, which stops it admitting OIDC callers.

Response fields:

FieldRequiredDescription
successnoTrue when the project no longer carries a contract, including when it carried none to begin with.
{"signatures":{"go":"func (x *AdminClient) DeleteProjectOIDCConfig(ctx context.Context, req *adminv1.DeleteProjectOIDCConfigRequest) (*adminv1.DeleteProjectOIDCConfigResponse, error)","python":"delete_project_oidc_config(req: admin_pb2.DeleteProjectOIDCConfigRequest) -\u003e DeleteProjectOIDCConfigResponse","typescript":"deleteProjectOIDCConfig(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.DeleteProjectOIDCConfigRequestSchema\u003e): Promise\u003cDeleteProjectOIDCConfigResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.DeleteProjectOIDCConfigRequest{}\n\n\tresp, err := client.Admin().DeleteProjectOIDCConfig(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/admin/deleteprojectoidcconfig\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.admin.v1 import admin_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 = admin_pb2.DeleteProjectOIDCConfigRequest()\ntry:\n    result = client.admin.delete_project_oidc_config(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.admin.deleteProjectOIDCConfig(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../projects/proj_01H.../oidc\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/customers/{customer_id}/projects/{project_id}/oidc","slug":"delete-project-oidc-config"}

Get system setting

Changed in v0.9.0 (new features): GetSystemSetting takes an optional include_config_event flag for guardrails.enabled. It returns the status of the latest push of that setting to your data planes in the last 24 hours.

Changed in v0.1.5 (bug fixes): Reading and writing a system setting whose key contains a colon (for example dataplane-url:<workspace_id>) now works over REST. GET and PUT /admin/v1/system-settings/{key} previously returned an empty 200 response for such keys; both the raw and the percent-encoded forms of the key now resolve.

Request fields:

FieldRequiredDescription
keynoDeployment-global system_settings key to read (e.g. "setup-completed").
include_config_eventnoWhen true, the response also carries config_event: the latest configuration push of the last 24 hours for this setting, so a caller can show whether a change has reached the data planes. Only a push that a change to this setting caused counts; a push for a guardrail, rule or other setting change does not. Supported only for "guardrails.enabled"; any other key returns INVALID_ARGUMENT. Unset or false, the response is unchanged.

Response fields:

FieldRequiredDescription
valuenoThe stored value; empty when the key is absent (see found).
foundnoTrue when the key exists with a non-empty value. UpsertSystemSetting rejects empty values (value has min_len: 1), so a stored key always has a non-empty value and this never diverges from raw key existence.
config_eventnoThe latest configuration push for this setting in the last 24 hours. Set only when include_config_event was true and such a push exists.
{"signatures":{"go":"func (x *AdminClient) GetSystemSetting(ctx context.Context, req *adminv1.GetSystemSettingRequest) (*adminv1.GetSystemSettingResponse, error)","python":"get_system_setting(req: admin_pb2.GetSystemSettingRequest) -\u003e GetSystemSettingResponse","typescript":"getSystemSetting(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.GetSystemSettingRequestSchema\u003e): Promise\u003cGetSystemSettingResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.GetSystemSettingRequest{}\n\n\tresp, err := client.Admin().GetSystemSetting(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/admin/getsystemsetting\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.admin.v1 import admin_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 = admin_pb2.GetSystemSettingRequest()\ntry:\n    result = client.admin.get_system_setting(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.admin.getSystemSetting(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/system-settings/{key}","slug":"get-system-setting"}

Upsert system setting

Changed in v0.11.0 (new features): An admin can now change two management plane address checks without restarting valet. The system settings oidc.discovery_allow_private_addresses and gateway_auth.jwks_allow_private_addresses override OIDC_DISCOVERY_ALLOW_PRIVATE_ADDRESSES and GATEWAY_AUTH_JWKS_ALLOW_PRIVATE_ADDRESSES. Each takes true, false or inherit, and UpsertSystemSetting refuses any other value for them.

Changed in v0.8.0 (bug fixes): Project default settings, project membership changes, the request-log mode, and rate-limit policies moved to another target now reach your gateways within the usual update cycle. They were previously saved but not pushed, so keys kept an old rate limit or fallback, a removed member kept the project's shared provider keys, and a moved policy kept limiting its old keys. A project-wide rate limit is also now enforced on keys with no settings of their own.

Changed in v0.1.5 (bug fixes): Reading and writing a system setting whose key contains a colon (for example dataplane-url:<workspace_id>) now works over REST. GET and PUT /admin/v1/system-settings/{key} previously returned an empty 200 response for such keys; both the raw and the percent-encoded forms of the key now resolve.

Request fields:

FieldRequiredDescription
keynoDeployment-global system_settings key to write (e.g. "deployment-mode").
valuenoValue to store under key. Must be non-empty: an empty write would read back as not-found (GetSystemSettingResponse.found is value != ""), so it is rejected rather than silently creating an invisible row.
if_absentnoWhen true, only insert if the key is absent (atomic ON CONFLICT DO NOTHING); an existing value is left untouched. When false, upsert (create or replace).

Response fields:

FieldRequiredDescription
wrotenoTrue when a row was written. With if_absent=true this is false if the key already existed (nothing was changed).
previousnoThe prior value before this call ("" when the key was absent), for idempotency reporting.
{"signatures":{"go":"func (x *AdminClient) UpsertSystemSetting(ctx context.Context, req *adminv1.UpsertSystemSettingRequest) (*adminv1.UpsertSystemSettingResponse, error)","python":"upsert_system_setting(req: admin_pb2.UpsertSystemSettingRequest) -\u003e UpsertSystemSettingResponse","typescript":"upsertSystemSetting(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.UpsertSystemSettingRequestSchema\u003e): Promise\u003cUpsertSystemSettingResponse\u003e","curl":"curl -X PUT \"${AGENTROUTER_BASE_URL}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"value\": \"...\",\n    \"if_absent\": 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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.UpsertSystemSettingRequest{}\n\n\tresp, err := client.Admin().UpsertSystemSetting(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/admin/upsertsystemsetting\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.admin.v1 import admin_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 = admin_pb2.UpsertSystemSettingRequest()\ntry:\n    result = client.admin.upsert_system_setting(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.admin.upsertSystemSetting(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 PUT \"${AGENTROUTER_BASE_URL}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"value\": \"...\",\n    \"if_absent\": false\n  }'"},"persona":"Admin","httpVerb":"PUT","httpPath":"/admin/v1/system-settings/{key}","slug":"upsert-system-setting"}

Clear system setting

Changed in v0.9.0 (new features): Data planes now carry stored_url, the URL stored for the data plane. When another organization uses the same data plane ID, stored_url is the first hostname your data plane declares, or empty. The new ClearSystemSetting unsets the proxy URL setting or the stored URL of one data plane.

Changed in v0.9.0 (deprecations): stored_url on data planes and ClearSystemSetting are deprecated. They go with the stored data plane URL in a later release.

Deprecated

What it does: Stores an empty value under a URL key, which then reads back as not-found (tetrateio/fraser#7281). UpsertSystemSetting rejects an empty value, so this is the API write that unsets a URL. Only the "proxy-url" key and the "dataplane-url:<data plane ID>" keys are accepted; any other key returns InvalidArgument. A clear of a "dataplane-url:" key is refused with FailedPrecondition when another organization uses the same data plane ID, like SetDataplaneURL. It leaves the data plane's default Project Gateway unchanged and sends the data plane its new URL configuration. Deprecated: a data plane declares its own hostnames from 0.7, and this goes with the stored data plane URL in a later release.

Request fields:

FieldRequiredDescription
keynoKey to clear. Only "proxy-url" and "dataplane-url:<data plane ID>" are accepted; any other key returns InvalidArgument.

Response fields:

FieldRequiredDescription
previousnoThe value before this call ("" when the key was absent or already clear).
{"signatures":{"go":"func (x *AdminClient) ClearSystemSetting(ctx context.Context, req *adminv1.ClearSystemSettingRequest) (*adminv1.ClearSystemSettingResponse, error)","python":"clear_system_setting(req: admin_pb2.ClearSystemSettingRequest) -\u003e ClearSystemSettingResponse","typescript":"clearSystemSetting(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ClearSystemSettingRequestSchema\u003e): Promise\u003cClearSystemSettingResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ClearSystemSettingRequest{}\n\n\tresp, err := client.Admin().ClearSystemSetting(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/admin/clearsystemsetting\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.admin.v1 import admin_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 = admin_pb2.ClearSystemSettingRequest()\ntry:\n    result = client.admin.clear_system_setting(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.admin.clearSystemSetting(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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 DELETE \"${AGENTROUTER_BASE_URL}/admin/v1/system-settings/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/admin/v1/system-settings/{key}","slug":"clear-system-setting"}

List dataplane rollout

Changed in v0.7.0 (new features): Rollout progress now reads per data plane as a fraction of its labelled projects, and rolls up to a fleet figure such as 7 of 9 that counts a data plane only when every project on it holds its current revision. Projects with no revision yet are left out of both, so a data plane serving only those reads 0 of 0. Each data plane also reports whether its guardrails union is current, beside those counts rather than folded into them.

What it does: Reads the rollout watermark per data plane and rolls it up to a fleet figure, which is the reading a platform admin watches a change land by. It counts against the per-project revision #8587 mints and introduces no counter of its own. A data plane is current when every project labelled on it holds that project's current revision, so the fleet figure is a count of data planes rather than of projects.

Request fields:

FieldRequiredDescription
customer_idnoRequired: the customer whose fleet this is.
dataplane_idsnoOptional: report only these data planes. Empty reports every data plane carrying at least one project label.

Response fields:

FieldRequiredDescription
dataplanesnoOne line per data plane, ordered by data plane id.
dataplanes_currentnoThe fleet figure, which is "7/9 data planes": how many data planes hold the current revision for EVERY project labelled on them, out of how many carry a label at all. A data plane with no labels is in neither number, and neither is a data plane listed at 0 of 0 because none of its projects has a revision yet: no revision was distributed to it, so it has no rollout to have finished.
dataplanes_labellednoundocumented
{"signatures":{"go":"func (x *AdminClient) ListDataplaneRollout(ctx context.Context, req *adminv1.ListDataplaneRolloutRequest) (*adminv1.ListDataplaneRolloutResponse, error)","python":"list_dataplane_rollout(req: admin_pb2.ListDataplaneRolloutRequest) -\u003e ListDataplaneRolloutResponse","typescript":"listDataplaneRollout(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListDataplaneRolloutRequestSchema\u003e): Promise\u003cListDataplaneRolloutResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplanes:rollout\" \\\n  -H \"Authorization: Bearer ak-${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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListDataplaneRolloutRequest{}\n\n\tresp, err := client.Admin().ListDataplaneRollout(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/admin/listdataplanerollout\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.admin.v1 import admin_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 = admin_pb2.ListDataplaneRolloutRequest()\ntry:\n    result = client.admin.list_dataplane_rollout(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.admin.listDataplaneRollout(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../dataplanes:rollout\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/admin/v1/customers/{customer_id}/dataplanes:rollout","slug":"list-dataplane-rollout"}

List projects served from

Changed in v0.7.0 (new features): You can now resolve a set of data planes to the projects served from them, so a region-bound rule attaches to those projects rather than to the infrastructure. Each project also reports the data planes outside your selection that serve it, because a project labelled in several regions is served from all of them. Nothing verifies that a data plane named for a region runs in it.

What it does: Resolves a set of data planes to the projects served from them, which is what a region-bound rule attaches to. The rule attaches to the projects rather than to the data planes on purpose. A project is deliberately labelled on data planes in several regions, because that is the HA mechanism, so a control anchored to infrastructure would reach every region the project is served from. Each project here therefore reports the selected data planes serving it AND the ones outside the selection, so an operator sees which projects the selection does not contain. Nothing verifies where a data plane runs. A region lives in the name an operator gave the data plane and in the address it reports, both of which are the operator's own strings, mirrored read-only.

Request fields:

FieldRequiredDescription
customer_idnoRequired: the customer whose data planes these are.
dataplane_idsyesRequired: the data planes the selection names. An operator picks them by the region in their names, and nothing checks that a data plane named for a region runs in it.

Response fields:

FieldRequiredDescription
projectsnoThe projects served from the selection, ordered by project slug.
dataplanes_serving_nothingnoSelected data plane ids that carry no project label, ordered. They are reported rather than dropped: a selection that reaches nothing is a typo or a data plane serving nobody, and both are worth seeing.
{"signatures":{"go":"func (x *AdminClient) ListProjectsServedFrom(ctx context.Context, req *adminv1.ListProjectsServedFromRequest) (*adminv1.ListProjectsServedFromResponse, error)","python":"list_projects_served_from(req: admin_pb2.ListProjectsServedFromRequest) -\u003e ListProjectsServedFromResponse","typescript":"listProjectsServedFrom(req: MessageInitShape\u003ctypeof tars_admin_v1_admin_pb.ListProjectsServedFromRequestSchema\u003e): Promise\u003cListProjectsServedFromResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/admin/v1/customers/cust_01H.../dataplanes:projectsServedFrom\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"dataplane_ids\": []\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\tadminv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/admin/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 := \u0026adminv1.ListProjectsServedFromRequest{}\n\n\tresp, err := client.Admin().ListProjectsServedFrom(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/admin/listprojectsservedfrom\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.admin.v1 import admin_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 = admin_pb2.ListProjectsServedFromRequest()\ntry:\n    result = client.admin.list_projects_served_from(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.admin.listProjectsServedFrom(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"admin\",\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}/admin/v1/customers/cust_01H.../dataplanes:projectsServedFrom\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"dataplane_ids\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/admin/v1/customers/{customer_id}/dataplanes:projectsServedFrom","slug":"list-projects-served-from"}