Policy

Package: agentrouter.policy.v1 Service: PolicyService

Endpoints

Create a budget policy

Changed in v0.11.0 (new features): An organization admin can now create a project budget, which applies to every API key in the project. With the BLOCK action the budget stops traffic at its limit, and with the default MONITOR action it records spend and alerts without stopping traffic. A project admin cannot create one or move another budget onto project scope, and can still edit, enable, disable and delete their own project's budget.

Changed in v0.10.0 (security updates): Project admins can now create budgets only for their own project's API keys, and edit, enable, disable or delete only the budgets of their own project and its API keys. Team, user, tag and organization-wide budgets, and other projects' budgets, need an organization admin.

Changed in v0.4.0 (bug fixes): CreateBudgetPolicy now accepts only the released TEAM, TEAM_PER_USER_DEFAULT, and API_KEY scopes. Existing policies in legacy scopes remain available for reads, updates, enforcement, and resolution.

Changed in v0.3.0 (behaviour changes): Per-key budget storage changes with migration 0131. If two per-key budgets were active on two keys of the same client at the same intent, the upgrade keeps the earliest and deactivates the rest, and the surviving limit now applies to the client's combined spend.

Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.

Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.

Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.

What it does: Creates a new budget policy. For API_KEY scope, the named key's client and project are resolved under its row lock. Returns ABORTED if the key's project changed after authorization; a retry must still satisfy the request project's ownership check. A PROJECT scope policy applies to every key of budget_policy.project_id, and stops traffic at its limit only with action BLOCK. Only an organization admin can create one (PERMISSION_DENIED otherwise), and the project must be a live project of customer_id (NOT_FOUND otherwise).

Request fields:

FieldRequiredDescription
budget_policyyesRequired: policy to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
budget_policynoThe created policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateBudgetPolicy(ctx context.Context, req *policyv1.CreateBudgetPolicyRequest) (*policyv1.CreateBudgetPolicyResponse, error)","python":"create_budget_policy(req: policy_pb2.CreateBudgetPolicyRequest) -\u003e CreateBudgetPolicyResponse","typescript":"createBudgetPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateBudgetPolicyRequestSchema\u003e): Promise\u003cCreateBudgetPolicyResponse\u003e","cli":"tare api policy budget-policies create --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"budget_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateBudgetPolicyRequest{}\n\n\tresp, err := client.Policy().CreateBudgetPolicy(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/policy/createbudgetpolicy\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.policy.v1 import policy_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 = policy_pb2.CreateBudgetPolicyRequest()\ntry:\n    result = client.policy.create_budget_policy(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.policy.createBudgetPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies create --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"budget_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies","slug":"create-a-budget-policy"}

Get a budget policy

Changed in v0.6.0 (new features): Budget policy reads now include the stored target client's name and, when spending is requested, the number of keys matching a tag budget. Integrations can display these details without separate database reads.

Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.

What it does: Returns a single budget policy by id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to fetch.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
include_spendnoWhen true the returned policy carries spend, its current-period spend measured from the usage rollups (one rollup scan, plus the team roster for team scopes). Off by default so a plain read stays a single row lookup.

Response fields:

FieldRequiredDescription
budget_policynoThe requested policy.
{"signatures":{"go":"func (x *PolicyClient) GetBudgetPolicy(ctx context.Context, req *policyv1.GetBudgetPolicyRequest) (*policyv1.GetBudgetPolicyResponse, error)","python":"get_budget_policy(req: policy_pb2.GetBudgetPolicyRequest) -\u003e GetBudgetPolicyResponse","typescript":"getBudgetPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetBudgetPolicyRequestSchema\u003e): Promise\u003cGetBudgetPolicyResponse\u003e","cli":"tare api policy budget-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetBudgetPolicyRequest{}\n\n\tresp, err := client.Policy().GetBudgetPolicy(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/policy/getbudgetpolicy\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.policy.v1 import policy_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 = policy_pb2.GetBudgetPolicyRequest()\ntry:\n    result = client.policy.get_budget_policy(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.policy.getBudgetPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-policies/{id}","slug":"get-a-budget-policy"}

Get budget spend history

Changed in v0.6.0 (new features): Administrators can preview up to 12 UTC months of billable spend for a team, its highest-spending member, or an API key before creating a budget, with month/spend filters, sorting and pagination. History uses current team membership and rolled-up managed/BYOK usage, excludes passthrough, preserves decimal precision and fills missing months with zero; without filters or pagination it returns all requested months oldest first, and user sessions require tenant budget-read permission.

What it does: Returns monthly billable spend for a target, even before a budget policy exists. Like other budget reads, this is a tenant-wide budget_policies.read operation, not a project-scoped read. RBAC and policy_reader scope authorization follow the other budget reads. customer_id remains explicit so authorization resolves the tenant before the handler runs; API-key boundaries apply on either authorization path. Project-bound non-admin API keys cannot call this organization operation.

Request fields:

FieldRequiredDescription
customer_idyesRequired tenant scope. Must match the authenticated principal's customer when that principal carries one.
scope_typeyesRequired: TEAM, TEAM_PER_USER_DEFAULT, or API_KEY.
group_idnoRequired UUID for team scopes; must be absent for API_KEY.
api_key_idnoRequired UUID for API_KEY; must be absent for team scopes. Measures this key alone, not all keys belonging to its client.
monthsnoNumber of UTC calendar months including the current partial month. Zero defaults to 6; otherwise must be between 1 and 12.
pagenoDefault and maximum page size: 12. Order by month or spend, asc or desc; default month asc. Equal spend uses month asc. page.filter is unsupported; use the typed bounds below. Keep scope, bounds, order and size on continuation.
start_monthnoInclusive first month, YYYY-MM-01, within the months window. Empty is unbounded.
end_monthnoInclusive last month, YYYY-MM-01, within the months window. Empty is unbounded.
min_spendnoInclusive minimum decimal USD, up to 28 integer and 10 fractional digits. No exponent notation. Empty is unbounded; reversed bounds match no months.
max_spendnoInclusive maximum decimal USD with the same format as min_spend. Empty is unbounded.

Response fields:

FieldRequiredDescription
historynoZero-filled monthly daily-rollup totals, filtered and ordered before paging. Missing and foreign-tenant targets produce zeros before spend filters apply. Without page or bounds, returns every requested month, oldest first.
pagenoContinue with the same request and page.page_token until empty.
total_countnoNumber of months matching the bounds before paging.
{"signatures":{"go":"func (x *PolicyClient) GetBudgetSpendHistory(ctx context.Context, req *policyv1.GetBudgetSpendHistoryRequest) (*policyv1.GetBudgetSpendHistoryResponse, error)","python":"get_budget_spend_history(req: policy_pb2.GetBudgetSpendHistoryRequest) -\u003e GetBudgetSpendHistoryResponse","typescript":"getBudgetSpendHistory(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetBudgetSpendHistoryRequestSchema\u003e): Promise\u003cGetBudgetSpendHistoryResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/spend-history?customer_id=cust_01H...\u0026scope_type=POLICY_SCOPE_TYPE_TEAM\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetBudgetSpendHistoryRequest{}\n\n\tresp, err := client.Policy().GetBudgetSpendHistory(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/policy/getbudgetspendhistory\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.policy.v1 import policy_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 = policy_pb2.GetBudgetSpendHistoryRequest()\ntry:\n    result = client.policy.get_budget_spend_history(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.policy.getBudgetSpendHistory(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/spend-history?customer_id=cust_01H...\u0026scope_type=POLICY_SCOPE_TYPE_TEAM\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-policies/spend-history","slug":"get-budget-spend-history"}

List budget policies

Changed in v0.6.0 (new features): Budget policy reads now include the stored target client's name and, when spending is requested, the number of keys matching a tag budget. Integrations can display these details without separate database reads.

Changed in v0.4.0 (behaviour changes): Listing budget policies now returns INVALID_ARGUMENT for a non-empty page.filter or an unsupported page.order_by, including multiple sort fields. These inputs were previously ignored.

Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.

What it does: Returns budget policies matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs. order_by accepts a single field, one of name, spend_limit, created_at and updated_at, with an optional asc/ desc suffix (default name asc); any other field is INVALID_ARGUMENT. filter is declared on the shared message but not implemented here, and is rejected rather than ignored. The page token carries only the offset and does not bind it to order_by. Clear page_token when changing order_by to restart from the first page; reusing a token applies its old offset to the new order.
searchnoOptional case-insensitive substring search on the policy name, the targeted team's name. The targeted user's name and email are also searched only within the permission and directory boundary used for returned identity fields. Applies to results, total and stats. % and _ match literally.
scope_typesnoFilter to policies with these scope types.
statusesnoFilter to policies in these statuses.
group_idnoFilter to policies targeting this group_id.
user_idnoFilter to policies targeting this user_id.
api_key_idnoFilter to the policies that GOVERN this key -- those whose stored (client, project) is the key's effective client and project -- and only those. An api_key policy caps the key's client, so a key's budget may be a policy authored on the key it was rotated from, and a policy still naming a key that has since been attached to another client no longer governs it and is not listed for it.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
include_spendnoWhen true every returned policy carries spend (see BudgetPolicy.spend): one rollup scan per row, plus the team roster for team scopes. Lets a list page render live spend from one call instead of one read per row. A row whose measurement fails is still listed, without spend; the failure is logged server-side and a per-policy read can retry it.
include_statsnoWhen true the response carries stats: the near/over-limit split of the ACTIVE policies matching this request's filters. Measures at most 500 active policies in the requested sort order, independently of paging. stats.truncated signals a larger matching set. Individual measurement failures are counted in stats.measurement_failed_count; they do not discard the policy list or the other statistics.
near_limit_threshold_pctnoPercent of spend_limit at or above which an active policy counts towards stats.near_limit_count (1-100). Zero means the default, 80.
include_customer_spendnoWhen true the response carries customer_spend, the tenant's month-to-date spend. One rollup scan, independent of the policies listed, so a headline can be refreshed on its own clock without include_stats.

Response fields:

FieldRequiredDescription
budget_policiesnoPolicies matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
statsnoNear/over-limit split; present only when the request set include_stats.
customer_spendnoThe tenant's spend in the current MONTHLY window across every api key it owns, whether or not any policy targets them; present only when the request set include_customer_spend. MEASURED, never summed from policy rows: project and system policies overlap the keys inside them, so their amounts are not additive. members is empty and available is true.
{"signatures":{"go":"func (x *PolicyClient) ListBudgetPolicies(ctx context.Context, req *policyv1.ListBudgetPoliciesRequest) (*policyv1.ListBudgetPoliciesResponse, error)","python":"list_budget_policies(req: policy_pb2.ListBudgetPoliciesRequest) -\u003e ListBudgetPoliciesResponse","typescript":"listBudgetPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListBudgetPoliciesRequestSchema\u003e): Promise\u003cListBudgetPoliciesResponse\u003e","cli":"tare api policy budget-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListBudgetPoliciesRequest{}\n\n\tresp, err := client.Policy().ListBudgetPolicies(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/policy/listbudgetpolicies\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.policy.v1 import policy_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 = policy_pb2.ListBudgetPoliciesRequest()\ntry:\n    result = client.policy.list_budget_policies(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.policy.listBudgetPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-policies","slug":"list-budget-policies"}

Get budget consumption

Changed in v0.7.0 (new features): GetBudgetConsumption reports what an Organization, or each project inside it, has consumed in the current period, in spend and in tokens, with the budget set at that scope when there is one. A scope with no budget is reported as having none rather than as zero, and the read states no enforcement behaviour: what happens when a budget is reached stays with the budget policy that defines it.

What it does: Reports what an organization, or the projects inside it, consumed in the current accounting period, and the budget in force at that scope when one is set. Exactly two scopes are reported, the organization and a project, and this surface has no others. Consumption is measured from the usage rollups at read time and never stored, over the same two windows BudgetSpend is computed from: daily rollups before the current UTC day, hourly rollups from it on. It is reported in money and in tokens. The budget is a money figure. No budget in this system is denominated in tokens, and no field on this RPC is a token ceiling. budget is read from the active budget policy already stored at that scope, and is absent when there is none, so a caller can say that no budget is set rather than showing a zero. This RPC authors nothing: an organization admin creates a project budget with CreateBudgetPolicy, which does not create an organization budget. This RPC states consumption and limit, and says nothing about what happens when the limit is reached. That belongs to the budget system -- BudgetPolicy.action, the alert evaluator and the enforcement resolver -- and no field here adds to it or restates it.

Request fields:

FieldRequiredDescription
customer_idyesRequired: organization to report. Also the tenant boundary a scoped management key is checked against.
project_idnoOptional: report this one project. A project id that is not a live project of customer_id returns NOT_FOUND, which reads the same as a project id that was never used.
include_projectsnoWhen true the response carries one projects entry per live project of the organization, projects that consumed nothing included, so a table renders from one call. Ignored when project_id is set.

Response fields:

FieldRequiredDescription
organizationnoThe organization's consumption, measured over every api key the tenant owns. Measured rather than summed from projects: a key with no project, a key whose project was deleted and a key naming a project row that is gone all count here and in no project entry, so the entries do not add up to this. Absent for a caller pinned to one project. Such a credential is refused outright when it asks the organization-wide question, so it does not receive the organization's figures as part of an answer about its own project either.
projectsnoThe project named by project_id, or every live project when include_projects is set, ordered by billable_spend descending and then by project_id. Empty otherwise.
{"signatures":{"go":"func (x *PolicyClient) GetBudgetConsumption(ctx context.Context, req *policyv1.GetBudgetConsumptionRequest) (*policyv1.GetBudgetConsumptionResponse, error)","python":"get_budget_consumption(req: policy_pb2.GetBudgetConsumptionRequest) -\u003e GetBudgetConsumptionResponse","typescript":"getBudgetConsumption(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetBudgetConsumptionRequestSchema\u003e): Promise\u003cGetBudgetConsumptionResponse\u003e","cli":"tare api policy budget-consumption get --customer-id $CUSTOMER_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-consumption?customer_id=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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetBudgetConsumptionRequest{}\n\n\tresp, err := client.Policy().GetBudgetConsumption(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/policy/getbudgetconsumption\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.policy.v1 import policy_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 = policy_pb2.GetBudgetConsumptionRequest()\ntry:\n    result = client.policy.get_budget_consumption(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.policy.getBudgetConsumption(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-consumption get --customer-id $CUSTOMER_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-consumption?customer_id=cust_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-consumption","slug":"get-budget-consumption"}

Update a budget policy

Changed in v0.11.0 (new features): An organization admin can now create a project budget, which applies to every API key in the project. With the BLOCK action the budget stops traffic at its limit, and with the default MONITOR action it records spend and alerts without stopping traffic. A project admin cannot create one or move another budget onto project scope, and can still edit, enable, disable and delete their own project's budget.

Changed in v0.10.0 (security updates): Project admins can now create budgets only for their own project's API keys, and edit, enable, disable or delete only the budgets of their own project and its API keys. Team, user, tag and organization-wide budgets, and other projects' budgets, need an organization admin.

Changed in v0.3.0 (behaviour changes): Per-key budget storage changes with migration 0131. If two per-key budgets were active on two keys of the same client at the same intent, the upgrade keeps the earliest and deactivates the rest, and the surviving limit now applies to the client's combined spend.

Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.

Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.

Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.

Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.

What it does: Updates mutable budget policy fields. Omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. The policy id must be set inside the budget_policy field. Restating the same api_key_id on an existing API_KEY policy preserves its stored client and project; supplying a different key retargets it. When a key target is supplied, returns ABORTED if its project changed after authorization. A retry must still satisfy the request project's ownership check. Moving a policy of another scope onto PROJECT scope needs an organization admin (PERMISSION_DENIED otherwise).

Request fields:

FieldRequiredDescription
budget_policyyesRequired: policy to update. budget_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched; enum fields set to *_UNSPECIFIED leave the existing value untouched.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
budget_policynoThe updated policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) UpdateBudgetPolicy(ctx context.Context, req *policyv1.UpdateBudgetPolicyRequest) (*policyv1.UpdateBudgetPolicyResponse, error)","python":"update_budget_policy(req: policy_pb2.UpdateBudgetPolicyRequest) -\u003e UpdateBudgetPolicyResponse","typescript":"updateBudgetPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateBudgetPolicyRequestSchema\u003e): Promise\u003cUpdateBudgetPolicyResponse\u003e","cli":"tare api policy budget-policies update --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"budget_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateBudgetPolicyRequest{}\n\n\tresp, err := client.Policy().UpdateBudgetPolicy(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/policy/updatebudgetpolicy\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.policy.v1 import policy_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 = policy_pb2.UpdateBudgetPolicyRequest()\ntry:\n    result = client.policy.update_budget_policy(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.policy.updateBudgetPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies update --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"budget_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{budget_policy.id}","slug":"update-a-budget-policy"}

Delete a budget policy

Changed in v0.10.0 (security updates): Project admins can now create budgets only for their own project's API keys, and edit, enable, disable or delete only the budgets of their own project and its API keys. Team, user, tag and organization-wide budgets, and other projects' budgets, need an organization admin.

Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.

What it does: Deactivates a budget policy (is_active = false); the row remains, still listed under statuses INACTIVE, and can be removed with PurgeBudgetPolicy once inactive.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to delete.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
{"signatures":{"go":"func (x *PolicyClient) DeleteBudgetPolicy(ctx context.Context, req *policyv1.DeleteBudgetPolicyRequest) (*policyv1.DeleteBudgetPolicyResponse, error)","python":"delete_budget_policy(req: policy_pb2.DeleteBudgetPolicyRequest) -\u003e DeleteBudgetPolicyResponse","typescript":"deleteBudgetPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteBudgetPolicyRequestSchema\u003e): Promise\u003cDeleteBudgetPolicyResponse\u003e","cli":"tare api policy budget-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteBudgetPolicyRequest{}\n\n\tresp, err := client.Policy().DeleteBudgetPolicy(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/policy/deletebudgetpolicy\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.policy.v1 import policy_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 = policy_pb2.DeleteBudgetPolicyRequest()\ntry:\n    result = client.policy.delete_budget_policy(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.policy.deleteBudgetPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}","slug":"delete-a-budget-policy"}

Set budget policy status

Changed in v0.10.0 (security updates): Project admins can now create budgets only for their own project's API keys, and edit, enable, disable or delete only the budgets of their own project and its API keys. Team, user, tag and organization-wide budgets, and other projects' budgets, need an organization admin.

Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.

Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.

Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.

What it does: Toggles a budget policy's active/inactive state (is_active). Activation retries concurrent changes to the policy's stored scope, client or project. Returns ABORTED if the target cannot be stabilized within the retry limit; the caller may retry.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
statusyesRequired: new operational status for the policy.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
budget_policynoThe policy with the updated status.
{"signatures":{"go":"func (x *PolicyClient) SetBudgetPolicyStatus(ctx context.Context, req *policyv1.SetBudgetPolicyStatusRequest) (*policyv1.SetBudgetPolicyStatusResponse, error)","python":"set_budget_policy_status(req: policy_pb2.SetBudgetPolicyStatusRequest) -\u003e SetBudgetPolicyStatusResponse","typescript":"setBudgetPolicyStatus(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetBudgetPolicyStatusRequestSchema\u003e): Promise\u003cSetBudgetPolicyStatusResponse\u003e","cli":"tare api policy budget-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetBudgetPolicyStatusRequest{}\n\n\tresp, err := client.Policy().SetBudgetPolicyStatus(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/policy/setbudgetpolicystatus\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.policy.v1 import policy_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 = policy_pb2.SetBudgetPolicyStatusRequest()\ntry:\n    result = client.policy.set_budget_policy_status(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.policy.setBudgetPolicyStatus(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}/status","slug":"set-budget-policy-status"}

Purge a budget policy

Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.

Changed in v0.4.0 (new features): The API can now permanently remove an inactive budget policy without changing the existing deactivation behavior of DELETE. Without the admin scope, purge reaches only PROJECT and API_KEY policies in the request project. Callers with the admin scope can also purge inactive policies with other scopes in their customer.

What it does: Permanently removes an INACTIVE budget policy. DeleteBudgetPolicy only deactivates (budget_policies has no deleted_at column), so without this RPC an API-only operator could never remove a row. The policy must already be inactive -- deactivate it first through SetBudgetPolicyStatus or DeleteBudgetPolicy -- and that check is part of the delete statement itself, so a policy reactivated concurrently is left in place rather than destroyed. A caller without the admin scope may purge only PROJECT- and API_KEY-scoped policies within the request project. After request authorization, unknown policies and targets outside this allow-list both return NOT_FOUND. An active policy returns FAILED_PRECONDITION only if the caller is authorized to purge it. Alert history survives the purge with BudgetAlert.policy_id cleared (budget_alerts.policy_id is ON DELETE SET NULL), so ListBudgetAlerts can no longer find those alerts by policy_id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the inactive policy to remove permanently.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project context used to authorize this request. A caller without the admin scope may purge only PROJECT- or API_KEY-scoped policies whose project matches this value. After request authorization, other targets return NOT_FOUND. With the admin scope, the target may have another project or a tenant-wide scope.
{"signatures":{"go":"func (x *PolicyClient) PurgeBudgetPolicy(ctx context.Context, req *policyv1.PurgeBudgetPolicyRequest) (*policyv1.PurgeBudgetPolicyResponse, error)","python":"purge_budget_policy(req: policy_pb2.PurgeBudgetPolicyRequest) -\u003e PurgeBudgetPolicyResponse","typescript":"purgeBudgetPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.PurgeBudgetPolicyRequestSchema\u003e): Promise\u003cPurgeBudgetPolicyResponse\u003e","cli":"tare api policy budget-policies purge \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../purge\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.PurgeBudgetPolicyRequest{}\n\n\tresp, err := client.Policy().PurgeBudgetPolicy(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/policy/purgebudgetpolicy\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.policy.v1 import policy_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 = policy_pb2.PurgeBudgetPolicyRequest()\ntry:\n    result = client.policy.purge_budget_policy(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.policy.purgeBudgetPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-policies purge \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../purge\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}/purge","slug":"purge-a-budget-policy"}

List budget alerts

What it does: Returns system-fired budget alerts matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
policy_idnoFilter to alerts fired by this policy_id.
group_idnoFilter to alerts snapshotting this group_id.
user_idnoFilter to alerts snapshotting this user_id.
api_key_idnoFilter to alerts snapshotting this api_key_id.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
budget_alertsnoAlerts matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching alerts across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListBudgetAlerts(ctx context.Context, req *policyv1.ListBudgetAlertsRequest) (*policyv1.ListBudgetAlertsResponse, error)","python":"list_budget_alerts(req: policy_pb2.ListBudgetAlertsRequest) -\u003e ListBudgetAlertsResponse","typescript":"listBudgetAlerts(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListBudgetAlertsRequestSchema\u003e): Promise\u003cListBudgetAlertsResponse\u003e","cli":"tare api policy budget-alerts list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListBudgetAlertsRequest{}\n\n\tresp, err := client.Policy().ListBudgetAlerts(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/policy/listbudgetalerts\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.policy.v1 import policy_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 = policy_pb2.ListBudgetAlertsRequest()\ntry:\n    result = client.policy.list_budget_alerts(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.policy.listBudgetAlerts(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-alerts list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-alerts","slug":"list-budget-alerts"}

Get a budget alert

What it does: Returns a single budget alert by id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the alert to fetch.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
budget_alertnoThe requested alert.
{"signatures":{"go":"func (x *PolicyClient) GetBudgetAlert(ctx context.Context, req *policyv1.GetBudgetAlertRequest) (*policyv1.GetBudgetAlertResponse, error)","python":"get_budget_alert(req: policy_pb2.GetBudgetAlertRequest) -\u003e GetBudgetAlertResponse","typescript":"getBudgetAlert(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetBudgetAlertRequestSchema\u003e): Promise\u003cGetBudgetAlertResponse\u003e","cli":"tare api policy budget-alerts get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetBudgetAlertRequest{}\n\n\tresp, err := client.Policy().GetBudgetAlert(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/policy/getbudgetalert\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.policy.v1 import policy_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 = policy_pb2.GetBudgetAlertRequest()\ntry:\n    result = client.policy.get_budget_alert(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.policy.getBudgetAlert(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy budget-alerts get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-alerts/{id}","slug":"get-a-budget-alert"}

Create a user group

Changed in v0.10.0 (security updates): Creating, renaming or deleting a team, and adding or removing its users, through the API now needs an organization admin. Project admins can no longer change teams, which apply across every project. Users whose role lets them manage teams can still do so in the Admin Console.

What it does: Creates a new user group (team).

Request fields:

FieldRequiredDescription
user_groupyesRequired: group to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created group. Only an organization admin can write teams.
project_idyesRequired by the route. Teams belong to the organization, not a project, so this neither owns the group nor authorizes the caller.

Response fields:

FieldRequiredDescription
user_groupnoThe created group with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateUserGroup(ctx context.Context, req *policyv1.CreateUserGroupRequest) (*policyv1.CreateUserGroupResponse, error)","python":"create_user_group(req: policy_pb2.CreateUserGroupRequest) -\u003e CreateUserGroupResponse","typescript":"createUserGroup(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateUserGroupRequestSchema\u003e): Promise\u003cCreateUserGroupResponse\u003e","cli":"tare api policy user-groups create --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_group\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateUserGroupRequest{}\n\n\tresp, err := client.Policy().CreateUserGroup(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/policy/createusergroup\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.policy.v1 import policy_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 = policy_pb2.CreateUserGroupRequest()\ntry:\n    result = client.policy.create_user_group(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.policy.createUserGroup(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-groups create --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_group\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups","slug":"create-a-user-group"}

Get a user group

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

What it does: Returns a single user group by id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the group to fetch.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
user_groupnoThe requested group.
{"signatures":{"go":"func (x *PolicyClient) GetUserGroup(ctx context.Context, req *policyv1.GetUserGroupRequest) (*policyv1.GetUserGroupResponse, error)","python":"get_user_group(req: policy_pb2.GetUserGroupRequest) -\u003e GetUserGroupResponse","typescript":"getUserGroup(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetUserGroupRequestSchema\u003e): Promise\u003cGetUserGroupResponse\u003e","cli":"tare api policy user-groups get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetUserGroupRequest{}\n\n\tresp, err := client.Policy().GetUserGroup(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/policy/getusergroup\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.policy.v1 import policy_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 = policy_pb2.GetUserGroupRequest()\ntry:\n    result = client.policy.get_user_group(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.policy.getUserGroup(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-groups get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups/{id}","slug":"get-a-user-group"}

List user groups

Changed in v0.5.0 (behaviour changes): ListUserGroups now returns InvalidArgument for a non-empty page.filter or an unsupported page.order_by instead of silently ignoring them.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

What it does: Returns user groups matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs. page.order_by accepts a single field, one of name, member_count, created_at or updated_at, optionally followed by asc or desc (AIP-132). An empty order_by keeps the historical name asc. page.filter is not supported and is rejected rather than ignored.
searchnoOptional case-insensitive substring search on group name or description.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
has_membersnoWhen set, keeps only the teams that have members (true) or only the empty ones (false). Unset lists both. Optional because a plain bool cannot say "unset" apart from "false", and "only the empty teams" is a real query.
include_statsnoWhen true the response carries stats, the membership split over the same search. It is a second aggregate query, so it can see a slightly newer state than this page. Lets the list header render from one call instead of one page_size=1 query per aggregate.

Response fields:

FieldRequiredDescription
user_groupsnoGroups matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching groups across all pages. Unlike stats, this honours the has_members filter -- it is the count this page is paging through.
statsnoMembership split; present only when the request set include_stats.
{"signatures":{"go":"func (x *PolicyClient) ListUserGroups(ctx context.Context, req *policyv1.ListUserGroupsRequest) (*policyv1.ListUserGroupsResponse, error)","python":"list_user_groups(req: policy_pb2.ListUserGroupsRequest) -\u003e ListUserGroupsResponse","typescript":"listUserGroups(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListUserGroupsRequestSchema\u003e): Promise\u003cListUserGroupsResponse\u003e","cli":"tare api policy user-groups list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListUserGroupsRequest{}\n\n\tresp, err := client.Policy().ListUserGroups(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/policy/listusergroups\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.policy.v1 import policy_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 = policy_pb2.ListUserGroupsRequest()\ntry:\n    result = client.policy.list_user_groups(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.policy.listUserGroups(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-groups list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups","slug":"list-user-groups"}

Update a user group

Changed in v0.10.0 (security updates): Creating, renaming or deleting a team, and adding or removing its users, through the API now needs an organization admin. Project admins can no longer change teams, which apply across every project. Users whose role lets them manage teams can still do so in the Admin Console.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.

What it does: Updates mutable user group fields. Omitted/empty scalar string fields leave the existing value untouched. The group id must be set inside the user_group field.

Request fields:

FieldRequiredDescription
user_groupyesRequired: group to update. user_group.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. To remove a description rather than change it, see clear_description.
customer_idyesRequired: customer (tenant) that owns the target group. Only an organization admin can write teams.
project_idyesRequired by the route. Teams belong to the organization, not a project, so this neither owns the group nor authorizes the caller.
clear_descriptionnoWhen true, removes the group's description (fraser#8004). description is a plain proto3 string, so an empty user_group.description is indistinguishable on the wire from an omitted one -- both leave the existing description untouched, per the partial-update rule above. Declaring it optional string would carry presence instead, but changes the generated type of UserGroup.description for every reader; this flag adds the one missing intent without that churn. clear_description together with a non-empty user_group.description is rejected as INVALID_ARGUMENT: the two state opposite intents and there is no defensible winner.

Response fields:

FieldRequiredDescription
user_groupnoThe updated group with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) UpdateUserGroup(ctx context.Context, req *policyv1.UpdateUserGroupRequest) (*policyv1.UpdateUserGroupResponse, error)","python":"update_user_group(req: policy_pb2.UpdateUserGroupRequest) -\u003e UpdateUserGroupResponse","typescript":"updateUserGroup(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateUserGroupRequestSchema\u003e): Promise\u003cUpdateUserGroupResponse\u003e","cli":"tare api policy user-groups update --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_group\": {},\n    \"clear_description\": 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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateUserGroupRequest{}\n\n\tresp, err := client.Policy().UpdateUserGroup(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/policy/updateusergroup\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.policy.v1 import policy_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 = policy_pb2.UpdateUserGroupRequest()\ntry:\n    result = client.policy.update_user_group(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.policy.updateUserGroup(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-groups update --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_group\": {},\n    \"clear_description\": false\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group.id}","slug":"update-a-user-group"}

Delete a user group

Changed in v0.10.0 (security updates): Creating, renaming or deleting a team, and adding or removing its users, through the API now needs an organization admin. Project admins can no longer change teams, which apply across every project. Users whose role lets them manage teams can still do so in the Admin Console.

Changed in v0.5.0 (behaviour changes): DeleteUserGroup now refuses with FailedPrecondition while the team still has members or is the target of an active budget policy. Previously, deleting a team with members failed with an internal error; deleting a team without members also deleted its budget policies.

What it does: Deletes a user group. The group must be empty and unreferenced: a group that still has members, or that an active budget policy targets, is refused with FAILED_PRECONDITION, so callers remove the members (RemoveUserGroupMembers) and deactivate the policies first. Inactive budget policies targeting the group are deleted with it.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the group to delete.
customer_idyesRequired: customer (tenant) that owns the target group. Only an organization admin can write teams.
project_idyesRequired by the route. Teams belong to the organization, not a project, so this neither owns the group nor authorizes the caller.
{"signatures":{"go":"func (x *PolicyClient) DeleteUserGroup(ctx context.Context, req *policyv1.DeleteUserGroupRequest) (*policyv1.DeleteUserGroupResponse, error)","python":"delete_user_group(req: policy_pb2.DeleteUserGroupRequest) -\u003e DeleteUserGroupResponse","typescript":"deleteUserGroup(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteUserGroupRequestSchema\u003e): Promise\u003cDeleteUserGroupResponse\u003e","cli":"tare api policy user-groups delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteUserGroupRequest{}\n\n\tresp, err := client.Policy().DeleteUserGroup(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/policy/deleteusergroup\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.policy.v1 import policy_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 = policy_pb2.DeleteUserGroupRequest()\ntry:\n    result = client.policy.delete_user_group(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.policy.deleteUserGroup(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-groups delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{id}","slug":"delete-a-user-group"}

List user group members

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

What it does: Returns the users who belong to a group, ordered by name.

Request fields:

FieldRequiredDescription
user_group_idyesRequired: uuid of the group whose members to list.
pagenoCursor-pagination inputs. page.order_by accepts a single field, name or updated_at, optionally followed by asc or desc (AIP-132); empty keeps name asc. updated_at is the user row's last change, which AddUserGroupMembers writes, so updated_at desc approximates "recently added". page.filter is not supported and is rejected rather than ignored.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
searchnoOptional case-insensitive substring match on the member's name, or email when the caller holds users_reader and the member is inside the caller's directory boundary.

Response fields:

FieldRequiredDescription
membersnoThe group's members, one page's worth, in the requested order. The directory fields follow the UserGroupMember rule: filled only for a caller holding users_reader and members inside that caller's directory boundary.
pagenoCursor-pagination outputs.
totalnoTotal members across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListUserGroupMembers(ctx context.Context, req *policyv1.ListUserGroupMembersRequest) (*policyv1.ListUserGroupMembersResponse, error)","python":"list_user_group_members(req: policy_pb2.ListUserGroupMembersRequest) -\u003e ListUserGroupMembersResponse","typescript":"listUserGroupMembers(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListUserGroupMembersRequestSchema\u003e): Promise\u003cListUserGroupMembersResponse\u003e","cli":"tare api policy user-group-members list --user-group-id $USER_GROUP_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListUserGroupMembersRequest{}\n\n\tresp, err := client.Policy().ListUserGroupMembers(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/policy/listusergroupmembers\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.policy.v1 import policy_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 = policy_pb2.ListUserGroupMembersRequest()\ntry:\n    result = client.policy.list_user_group_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.policy.listUserGroupMembers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-group-members list --user-group-id $USER_GROUP_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups/{user_group_id}/members","slug":"list-user-group-members"}

Add user group members

Changed in v0.10.0 (security updates): Creating, renaming or deleting a team, and adding or removing its users, through the API now needs an organization admin. Project admins can no longer change teams, which apply across every project. Users whose role lets them manage teams can still do so in the Admin Console.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

What it does: Puts users into a group. A user already in another group is moved into this one, and the group they left comes back in moves -- the tag it overwrites is the only record of it. Ids that do not name a user are reported in failed; the rest of the batch still applies.

Request fields:

FieldRequiredDescription
user_group_idyesRequired: uuid of the group to add to.
user_idsyesRequired: users to put into the group. Repeated ids are collapsed.
customer_idyesRequired: customer (tenant) that owns the target group. Only an organization admin can write teams.
project_idyesRequired by the route. Teams belong to the organization, not a project, so this neither owns the group nor authorizes the caller.

Response fields:

FieldRequiredDescription
added_user_idsnoUsers now in the group, including any that already were.
failednoIds the call could not add. Empty on a fully applied batch.
movesnoUsers that were in another group before this call.
{"signatures":{"go":"func (x *PolicyClient) AddUserGroupMembers(ctx context.Context, req *policyv1.AddUserGroupMembersRequest) (*policyv1.AddUserGroupMembersResponse, error)","python":"add_user_group_members(req: policy_pb2.AddUserGroupMembersRequest) -\u003e AddUserGroupMembersResponse","typescript":"addUserGroupMembers(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.AddUserGroupMembersRequestSchema\u003e): Promise\u003cAddUserGroupMembersResponse\u003e","cli":"tare api policy user-group-members add --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.AddUserGroupMembersRequest{}\n\n\tresp, err := client.Policy().AddUserGroupMembers(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/policy/addusergroupmembers\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.policy.v1 import policy_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 = policy_pb2.AddUserGroupMembersRequest()\ntry:\n    result = client.policy.add_user_group_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.policy.addUserGroupMembers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-group-members add --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_ids\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group_id}/members","slug":"add-user-group-members"}

Remove user group members

Changed in v0.10.0 (security updates): Creating, renaming or deleting a team, and adding or removing its users, through the API now needs an organization admin. Project admins can no longer change teams, which apply across every project. Users whose role lets them manage teams can still do so in the Admin Console.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

What it does: Takes users out of a group. Removal is idempotent: a listed user who is not in the group is left alone rather than reported as an error.

Request fields:

FieldRequiredDescription
user_group_idyesRequired: uuid of the group to remove from.
user_idsyesRequired: users to take out of the group. Repeated ids are collapsed.
customer_idyesRequired: customer (tenant) that owns the target group. Only an organization admin can write teams.
project_idyesRequired by the route. Teams belong to the organization, not a project, so this neither owns the group nor authorizes the caller.

Response fields:

FieldRequiredDescription
removed_user_idsnoUsers this call took out of the group. A listed user who was not in it is absent here, and is not an error.
{"signatures":{"go":"func (x *PolicyClient) RemoveUserGroupMembers(ctx context.Context, req *policyv1.RemoveUserGroupMembersRequest) (*policyv1.RemoveUserGroupMembersResponse, error)","python":"remove_user_group_members(req: policy_pb2.RemoveUserGroupMembersRequest) -\u003e RemoveUserGroupMembersResponse","typescript":"removeUserGroupMembers(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.RemoveUserGroupMembersRequestSchema\u003e): Promise\u003cRemoveUserGroupMembersResponse\u003e","cli":"tare api policy user-group-members remove --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members/remove\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.RemoveUserGroupMembersRequest{}\n\n\tresp, err := client.Policy().RemoveUserGroupMembers(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/policy/removeusergroupmembers\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.policy.v1 import policy_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 = policy_pb2.RemoveUserGroupMembersRequest()\ntry:\n    result = client.policy.remove_user_group_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.policy.removeUserGroupMembers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy user-group-members remove --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members/remove\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_ids\": []\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group_id}/members/remove","slug":"remove-user-group-members"}

Create a tag schema entry

What it does: Adds an allowed (tag_key, tag_value) pair to the tag catalog.

Request fields:

FieldRequiredDescription
tag_schema_entryyesRequired: entry to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that will own the created entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
tag_schema_entrynoThe created entry with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateTagSchemaEntry(ctx context.Context, req *policyv1.CreateTagSchemaEntryRequest) (*policyv1.CreateTagSchemaEntryResponse, error)","python":"create_tag_schema_entry(req: policy_pb2.CreateTagSchemaEntryRequest) -\u003e CreateTagSchemaEntryResponse","typescript":"createTagSchemaEntry(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateTagSchemaEntryRequestSchema\u003e): Promise\u003cCreateTagSchemaEntryResponse\u003e","cli":"tare api policy tag-schema create --tag-schema-entry $TAG_SCHEMA_ENTRY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag_schema_entry\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateTagSchemaEntryRequest{}\n\n\tresp, err := client.Policy().CreateTagSchemaEntry(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/policy/createtagschemaentry\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.policy.v1 import policy_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 = policy_pb2.CreateTagSchemaEntryRequest()\ntry:\n    result = client.policy.create_tag_schema_entry(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.policy.createTagSchemaEntry(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy tag-schema create --tag-schema-entry $TAG_SCHEMA_ENTRY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag_schema_entry\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/tag-schema","slug":"create-a-tag-schema-entry"}

List tag schema entries

What it does: Returns allowed tag key/value pairs matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
tag_keynoFilter to entries with this tag_key.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
entriesnoEntries matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching entries across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListTagSchema(ctx context.Context, req *policyv1.ListTagSchemaRequest) (*policyv1.ListTagSchemaResponse, error)","python":"list_tag_schema(req: policy_pb2.ListTagSchemaRequest) -\u003e ListTagSchemaResponse","typescript":"listTagSchema(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListTagSchemaRequestSchema\u003e): Promise\u003cListTagSchemaResponse\u003e","cli":"tare api policy tag-schema list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/tag-schema\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListTagSchemaRequest{}\n\n\tresp, err := client.Policy().ListTagSchema(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/policy/listtagschema\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.policy.v1 import policy_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 = policy_pb2.ListTagSchemaRequest()\ntry:\n    result = client.policy.list_tag_schema(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.policy.listTagSchema(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy tag-schema list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/tag-schema\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/tag-schema","slug":"list-tag-schema-entries"}

Update a tag schema entry

Changed in v0.9.0 (new features): Administrators can edit or clear a tag's description from the Tags tab. Its key and value stay fixed, so API keys and policies using the tag are unaffected.

What it does: Replaces a tag catalog entry's description. The description is the only mutable field: tag_key and tag_value are the identity that api_key_tags rows and policy tag selectors match on, so they are fixed once created. An empty description clears it.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the entry to update.
customer_idyesRequired: customer (tenant) that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
descriptionyesRequired: the entry's new description, replacing the current one. Empty clears it. The description is the only field this RPC changes, so there is no update mask: every call is a description write. The server can't tell an omitted description from an empty one, so omitting it clears it too; the CLI makes --description mandatory to prevent that by accident.

Response fields:

FieldRequiredDescription
tag_schema_entrynoThe updated entry.
{"signatures":{"go":"func (x *PolicyClient) UpdateTagSchemaEntry(ctx context.Context, req *policyv1.UpdateTagSchemaEntryRequest) (*policyv1.UpdateTagSchemaEntryResponse, error)","python":"update_tag_schema_entry(req: policy_pb2.UpdateTagSchemaEntryRequest) -\u003e UpdateTagSchemaEntryResponse","typescript":"updateTagSchemaEntry(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateTagSchemaEntryRequestSchema\u003e): Promise\u003cUpdateTagSchemaEntryResponse\u003e","cli":"tare api policy tag-schema update \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID --description $DESCRIPTION","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"description\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateTagSchemaEntryRequest{}\n\n\tresp, err := client.Policy().UpdateTagSchemaEntry(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/policy/updatetagschemaentry\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.policy.v1 import policy_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 = policy_pb2.UpdateTagSchemaEntryRequest()\ntry:\n    result = client.policy.update_tag_schema_entry(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.policy.updateTagSchemaEntry(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy tag-schema update \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID --description $DESCRIPTION","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"description\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/tag-schema/{id}","slug":"update-a-tag-schema-entry"}

Delete a tag schema entry

What it does: Removes an allowed (tag_key, tag_value) pair from the tag catalog.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the entry to delete.
customer_idyesRequired: customer (tenant) that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
{"signatures":{"go":"func (x *PolicyClient) DeleteTagSchemaEntry(ctx context.Context, req *policyv1.DeleteTagSchemaEntryRequest) (*policyv1.DeleteTagSchemaEntryResponse, error)","python":"delete_tag_schema_entry(req: policy_pb2.DeleteTagSchemaEntryRequest) -\u003e DeleteTagSchemaEntryResponse","typescript":"deleteTagSchemaEntry(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteTagSchemaEntryRequestSchema\u003e): Promise\u003cDeleteTagSchemaEntryResponse\u003e","cli":"tare api policy tag-schema delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteTagSchemaEntryRequest{}\n\n\tresp, err := client.Policy().DeleteTagSchemaEntry(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/policy/deletetagschemaentry\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.policy.v1 import policy_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 = policy_pb2.DeleteTagSchemaEntryRequest()\ntry:\n    result = client.policy.delete_tag_schema_entry(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.policy.deleteTagSchemaEntry(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy tag-schema delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/tag-schema/{id}","slug":"delete-a-tag-schema-entry"}

Add an API key tag

Changed in v0.1.5 (bug fixes): Changing an API key's policy tags, or enabling or disabling a key, now takes effect on the data plane promptly. Previously these changes only reached a project's gateways on the periodic resync, so a re-tagged key kept its old routing and fallback for up to ~30 minutes, a rate-limit change from a tag was not applied until an unrelated policy edit, and a disabled key kept serving until the resync.

Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.

What it does: Attaches a (tag_key, tag_value) pair to an API key. Both must reference an existing TagSchemaEntry.

Request fields:

FieldRequiredDescription
api_key_idyesRequired: owning api_keys.id.
tag_keyyesRequired: tag key. Must reference an existing TagSchemaEntry.
tag_valueyesRequired: tag value. Must reference an existing TagSchemaEntry for tag_key.
customer_idyesRequired: customer (tenant) that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
api_key_tagnoThe created tag attachment.
{"signatures":{"go":"func (x *PolicyClient) AddApiKeyTag(ctx context.Context, req *policyv1.AddApiKeyTagRequest) (*policyv1.AddApiKeyTagResponse, error)","python":"add_api_key_tag(req: policy_pb2.AddApiKeyTagRequest) -\u003e AddApiKeyTagResponse","typescript":"addApiKeyTag(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.AddApiKeyTagRequestSchema\u003e): Promise\u003cAddApiKeyTagResponse\u003e","cli":"tare api policy api-key-tags add --api-key-id $API_KEY_ID --tag-key $TAG_KEY --tag-value $TAG_VALUE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag_key\": \"...\",\n    \"tag_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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.AddApiKeyTagRequest{}\n\n\tresp, err := client.Policy().AddApiKeyTag(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/policy/addapikeytag\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.policy.v1 import policy_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 = policy_pb2.AddApiKeyTagRequest()\ntry:\n    result = client.policy.add_api_key_tag(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.policy.addApiKeyTag(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy api-key-tags add --api-key-id $API_KEY_ID --tag-key $TAG_KEY --tag-value $TAG_VALUE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag_key\": \"...\",\n    \"tag_value\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/api-keys/{api_key_id}/tags","slug":"add-an-api-key-tag"}

List API key tags

Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.

What it does: Returns tags attached to an API key.

Request fields:

FieldRequiredDescription
api_key_idyesRequired: owning api_keys.id.
pagenoCursor-pagination inputs.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
api_key_tagsnoTags attached to the requested API key, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching tags across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListApiKeyTags(ctx context.Context, req *policyv1.ListApiKeyTagsRequest) (*policyv1.ListApiKeyTagsResponse, error)","python":"list_api_key_tags(req: policy_pb2.ListApiKeyTagsRequest) -\u003e ListApiKeyTagsResponse","typescript":"listApiKeyTags(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListApiKeyTagsRequestSchema\u003e): Promise\u003cListApiKeyTagsResponse\u003e","cli":"tare api policy api-key-tags list --api-key-id $API_KEY_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-keys/01H.../tags\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListApiKeyTagsRequest{}\n\n\tresp, err := client.Policy().ListApiKeyTags(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/policy/listapikeytags\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.policy.v1 import policy_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 = policy_pb2.ListApiKeyTagsRequest()\ntry:\n    result = client.policy.list_api_key_tags(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.policy.listApiKeyTags(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy api-key-tags list --api-key-id $API_KEY_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-keys/01H.../tags\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/api-keys/{api_key_id}/tags","slug":"list-api-key-tags"}

List API key IDs by tag

Changed in v0.9.0 (new features): GET /v1/policy/api-key-ids lists the IDs of API keys that carry a tag, or of keys with no tags (untagged=true). POST /v1/policy/api-key-tags/lookup returns the tags on up to 200 keys in one call.

What it does: Returns the IDs of the caller's API keys that carry a tag, or, with untagged set, the IDs of keys that carry none. Deleted keys are left out; revoked keys are included, since they can still be tagged.

Request fields:

FieldRequiredDescription
tag_keynoThe tag to match. Required unless untagged is set. internal: keys are reserved and refused.
tag_valuenoThe tag's value. Required unless untagged is set.
untaggednoReturn keys with no tags instead of keys carrying tag_key=tag_value.
pagenoCursor-pagination inputs.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
api_key_idsnoMatching API key IDs, one page's worth, in ID order.
pagenoCursor-pagination outputs.
totalnoTotal count of matching keys across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListApiKeyIdsByTag(ctx context.Context, req *policyv1.ListApiKeyIdsByTagRequest) (*policyv1.ListApiKeyIdsByTagResponse, error)","python":"list_api_key_ids_by_tag(req: policy_pb2.ListApiKeyIdsByTagRequest) -\u003e ListApiKeyIdsByTagResponse","typescript":"listApiKeyIdsByTag(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListApiKeyIdsByTagRequestSchema\u003e): Promise\u003cListApiKeyIdsByTagResponse\u003e","cli":"tare api policy api-key-tags list-key-ids","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-key-ids\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListApiKeyIdsByTagRequest{}\n\n\tresp, err := client.Policy().ListApiKeyIdsByTag(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/policy/listapikeyidsbytag\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.policy.v1 import policy_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 = policy_pb2.ListApiKeyIdsByTagRequest()\ntry:\n    result = client.policy.list_api_key_ids_by_tag(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.policy.listApiKeyIdsByTag(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy api-key-tags list-key-ids","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-key-ids\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/api-key-ids","slug":"list-api-key-ids-by-tag"}

Batch list API key tags

Changed in v0.9.0 (new features): GET /v1/policy/api-key-ids lists the IDs of API keys that carry a tag, or of keys with no tags (untagged=true). POST /v1/policy/api-key-tags/lookup returns the tags on up to 200 keys in one call.

What it does: Returns the tags on each of a set of API keys in one call. Deleted keys and keys the caller does not own are left out rather than erroring.

Request fields:

FieldRequiredDescription
api_key_idsnoThe API keys to read tags for. Capped at 200, the largest page a list RPC returns, so one page of keys resolves in a single call.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
api_key_tagsnoTags on the requested keys, ordered by api_key_id then tag_key. Each carries its api_key_id; a key with no tags contributes no rows.
{"signatures":{"go":"func (x *PolicyClient) BatchListApiKeyTags(ctx context.Context, req *policyv1.BatchListApiKeyTagsRequest) (*policyv1.BatchListApiKeyTagsResponse, error)","python":"batch_list_api_key_tags(req: policy_pb2.BatchListApiKeyTagsRequest) -\u003e BatchListApiKeyTagsResponse","typescript":"batchListApiKeyTags(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.BatchListApiKeyTagsRequestSchema\u003e): Promise\u003cBatchListApiKeyTagsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/policy/api-key-tags/lookup\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"api_key_ids\": [],\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.BatchListApiKeyTagsRequest{}\n\n\tresp, err := client.Policy().BatchListApiKeyTags(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/policy/batchlistapikeytags\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.policy.v1 import policy_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 = policy_pb2.BatchListApiKeyTagsRequest()\ntry:\n    result = client.policy.batch_list_api_key_tags(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.policy.batchListApiKeyTags(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/policy/api-key-tags/lookup\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"api_key_ids\": [],\n    \"customer_id\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/policy/api-key-tags/lookup","slug":"batch-list-api-key-tags"}

Remove an API key tag

Changed in v0.1.5 (bug fixes): Changing an API key's policy tags, or enabling or disabling a key, now takes effect on the data plane promptly. Previously these changes only reached a project's gateways on the periodic resync, so a re-tagged key kept its old routing and fallback for up to ~30 minutes, a rate-limit change from a tag was not applied until an unrelated policy edit, and a disabled key kept serving until the resync.

Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.

What it does: Detaches a tag from an API key.

Request fields:

FieldRequiredDescription
api_key_idyesRequired: owning api_keys.id.
idyesRequired: uuid of the tag attachment to remove.
customer_idyesRequired: customer (tenant) that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idyesRequired: project that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
{"signatures":{"go":"func (x *PolicyClient) RemoveApiKeyTag(ctx context.Context, req *policyv1.RemoveApiKeyTagRequest) (*policyv1.RemoveApiKeyTagResponse, error)","python":"remove_api_key_tag(req: policy_pb2.RemoveApiKeyTagRequest) -\u003e RemoveApiKeyTagResponse","typescript":"removeApiKeyTag(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.RemoveApiKeyTagRequestSchema\u003e): Promise\u003cRemoveApiKeyTagResponse\u003e","cli":"tare api policy api-key-tags remove --api-key-id $API_KEY_ID \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.RemoveApiKeyTagRequest{}\n\n\tresp, err := client.Policy().RemoveApiKeyTag(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/policy/removeapikeytag\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.policy.v1 import policy_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 = policy_pb2.RemoveApiKeyTagRequest()\ntry:\n    result = client.policy.remove_api_key_tag(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.policy.removeApiKeyTag(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy api-key-tags remove --api-key-id $API_KEY_ID \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/api-keys/{api_key_id}/tags/{id}","slug":"remove-an-api-key-tag"}

Get the effective policy for a scope

Changed in v0.10.0 (behaviour changes): Active admin-scoped admin secrets gain the admin_console machine role at management-plane startup, so the Admin Console can read the effective attribute-routing policy of a key or a tag preview, and a policy's coverage. The role is not assignable to users or groups.

Changed in v0.8.0 (behaviour changes): Attribute-based routing has two scopes, project and API key: a key's own routing policy replaces its project's. A tag preview returns the project's policy only when project_id is supplied, and no policy otherwise. Organization and tag policies are no longer resolved.

Changed in v0.8.0 (new features): A project or API key rate-limit policy can now limit requests per minute, requests per hour and tokens per minute beside tokens per hour, in any mix. Existing per-hour values stay. A refused request gets a 429 naming the policy and its window when the data plane can tell which policy set the limit. UpdateRateLimitPolicy removes one limit through clear_dimensions, GetEffectivePolicy names the dimension of each entry, and period has no effect. count_tokens calls count against no rate limit.

Changed in v0.6.0 (bug fixes): The effective fallback-policy view now merges fallback entries per protected model across scopes and folds bound allow-lists over the merged set, matching what the data plane enforces. A protected model inherited from a broader scope is no longer hidden when a bound policy exists, and each entry reports the policy that supplied it.

Changed in v0.5.0 (new features): PolicyService can explain which attribute-routing policy governs a key or tag preview. It returns the enabled winner, ordered rules and precedence details, and reports how many eligible keys are covered. These views require the attribute_routing_policies.read permission.

What it does: Resolves every BudgetPolicy applicable to a scope-target tuple down to the single clamp-winning policy.

Request fields:

FieldRequiredDescription
scope_typeyesRequired: scope type of the target to resolve.
group_idnoTeam target. Set when scope_type targets a group (see PolicyScopeType).
user_idnoUser target. Set when scope_type = POLICY_SCOPE_TYPE_USER.
api_key_idnoAPI key target. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY, or to resolve an API_KEY_TAG match against that key's attached tags.
tagsnoTag key/value selector. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY_TAG and api_key_id is not supplied.
customer_idnoOptional: customer (tenant) scope. Merged with the caller's authenticated claims (resolvePolicyCustomerID); reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note.
project_idnoOptional and, for scope_type = API_KEY, IGNORED: the server derives the key's project scope itself from the api_keys row identified by api_key_id (resolveApiKeyScope), the same way the dataplane's runtime policy resolvers scope a key's policies -- a caller-supplied project_id is never trusted for resolution. Only consulted for scope_type = API_KEY_TAG, where there is no api_key_id to derive it from.
viewnoOptional family view. Unknown values are rejected. The attribute-routing view uses only key and tag-preview targets and returns no legacy families.

Response fields:

FieldRequiredDescription
effective_policynoThe resolved effective policy for the requested scope-target tuple.
{"signatures":{"go":"func (x *PolicyClient) GetEffectivePolicy(ctx context.Context, req *policyv1.GetEffectivePolicyRequest) (*policyv1.GetEffectivePolicyResponse, error)","python":"get_effective_policy(req: policy_pb2.GetEffectivePolicyRequest) -\u003e GetEffectivePolicyResponse","typescript":"getEffectivePolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetEffectivePolicyRequestSchema\u003e): Promise\u003cGetEffectivePolicyResponse\u003e","cli":"tare api policy effective --scope-type $SCOPE_TYPE","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/effective-policy?scope_type=POLICY_SCOPE_TYPE_TEAM\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetEffectivePolicyRequest{}\n\n\tresp, err := client.Policy().GetEffectivePolicy(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/policy/geteffectivepolicy\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.policy.v1 import policy_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 = policy_pb2.GetEffectivePolicyRequest()\ntry:\n    result = client.policy.get_effective_policy(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.policy.getEffectivePolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy effective --scope-type $SCOPE_TYPE","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/effective-policy?scope_type=POLICY_SCOPE_TYPE_TEAM\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/effective-policy","slug":"get-the-effective-policy-for-a-scope"}

Get policy coverage for a scope

Changed in v0.10.0 (behaviour changes): Active admin-scoped admin secrets gain the admin_console machine role at management-plane startup, so the Admin Console can read the effective attribute-routing policy of a key or a tag preview, and a policy's coverage. The role is not assignable to users or groups.

Changed in v0.8.0 (behaviour changes): Attribute-based routing has two scopes, project and API key: a key's own routing policy replaces its project's. A tag preview returns the project's policy only when project_id is supplied, and no policy otherwise. Organization and tag policies are no longer resolved.

Changed in v0.5.0 (new features): PolicyService can explain which attribute-routing policy governs a key or tag preview. It returns the enabled winner, ordered rules and precedence details, and reports how many eligible keys are covered. These views require the attribute_routing_policies.read permission.

Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.

What it does: Reports whether a scope reference has at least one applicable BudgetPolicy, and lists which ones apply.

Request fields:

FieldRequiredDescription
scope_typenoRequired for legacy selector coverage; must be unspecified for policy-ID coverage.
group_idnoTeam target. Set when scope_type targets a group (see PolicyScopeType).
user_idnoUser target. Set when scope_type = POLICY_SCOPE_TYPE_USER.
api_key_idnoAPI key target. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY, or to check coverage for an API_KEY_TAG match against that key's attached tags.
tagsnoTag key/value selector. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY_TAG and api_key_id is not supplied.
customer_idnoOptional tenant context, checked against the authenticated caller.
project_idnoOptional project context. For policy-ID coverage it must match the stored project boundary.
attribute_routing_policy_idnoOptional attribute-routing policy ID. Requires attribute_routing_policies.read at the stored policy target. scope_type must be unspecified and group_id/user_id/api_key_id/tags absent. Tenant/project hints cannot change the stored target; conflicting hints fail. Without this field, legacy selector behavior is unchanged.

Response fields:

FieldRequiredDescription
coveragenoCoverage result for the requested scope reference.
attribute_routing_coveragenoOnly present for attribute_routing_policy_id requests; coverage is absent.
{"signatures":{"go":"func (x *PolicyClient) GetPolicyCoverage(ctx context.Context, req *policyv1.GetPolicyCoverageRequest) (*policyv1.GetPolicyCoverageResponse, error)","python":"get_policy_coverage(req: policy_pb2.GetPolicyCoverageRequest) -\u003e GetPolicyCoverageResponse","typescript":"getPolicyCoverage(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetPolicyCoverageRequestSchema\u003e): Promise\u003cGetPolicyCoverageResponse\u003e","cli":"tare api policy coverage","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/coverage\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetPolicyCoverageRequest{}\n\n\tresp, err := client.Policy().GetPolicyCoverage(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/policy/getpolicycoverage\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.policy.v1 import policy_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 = policy_pb2.GetPolicyCoverageRequest()\ntry:\n    result = client.policy.get_policy_coverage(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.policy.getPolicyCoverage(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy coverage","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/coverage\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/coverage","slug":"get-policy-coverage-for-a-scope"}

Create a rate-limit policy

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.8.0 (new features): A project or API key rate-limit policy can now limit requests per minute, requests per hour and tokens per minute beside tokens per hour, in any mix. Existing per-hour values stay. A refused request gets a 429 naming the policy and its window when the data plane can tell which policy set the limit. UpdateRateLimitPolicy removes one limit through clear_dimensions, GetEffectivePolicy names the dimension of each entry, and period has no effect. count_tokens calls count against no rate limit.

Changed in v0.7.0 (new features): A rate-limit policy now carries a display_name, the public label a caller will see when that limit refuses a request. Existing policies take their name as the label, and a policy created without one does the same, so a platform operator only sets it when the name is not meant for callers. The label is stored and returned for now; the refusal body that prints it is still to come.

What it does: Creates a new rate-limit policy. A policy sets any mix of six limits, and each one applies on its own. A dimension left at 0 is unset and has no limit. - input_tokens_per_hour: input (prompt) tokens per rolling hour. - output_tokens_per_hour: output (completion) tokens per rolling hour. - total_tokens_per_hour: input plus output tokens per rolling hour. This is the "tokens per hour" limit. - total_tokens_per_minute: input plus output tokens per rolling minute. - requests_per_minute: requests per rolling minute. Each request counts 1 when it arrives. - requests_per_hour: requests per rolling hour. requests_per_minute, requests_per_hour and total_tokens_per_minute are accepted only with scope_type PROJECT or API_KEY and action BLOCK. The server refuses them on any other scope or action with InvalidArgument. Tag, system and monitor policies keep the first three dimensions. Every dimension that is set must be between 1 and 1,000,000,000. The server refuses any other value with InvalidArgument. A project-scope limit is counted for each API key in the project on its own, not shared across the project. The period field has no effect: the server stores and returns it, and each dimension's window comes from the dimension's name. The server refuses the policy with FailedPrecondition when it sets one of the three newer dimensions and a data plane serving the target project reports a build older than 0.8.0, or no build.

Request fields:

FieldRequiredDescription
rate_limit_policyyesRequired: policy to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller.
project_idyesRequired: project that will own the created policy. Read by the project_owner persona to authorize the caller.

Response fields:

FieldRequiredDescription
rate_limit_policynoThe created policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateRateLimitPolicy(ctx context.Context, req *policyv1.CreateRateLimitPolicyRequest) (*policyv1.CreateRateLimitPolicyResponse, error)","python":"create_rate_limit_policy(req: policy_pb2.CreateRateLimitPolicyRequest) -\u003e CreateRateLimitPolicyResponse","typescript":"createRateLimitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateRateLimitPolicyRequestSchema\u003e): Promise\u003cCreateRateLimitPolicyResponse\u003e","cli":"tare api policy rate-limit-policies create --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"rate_limit_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateRateLimitPolicyRequest{}\n\n\tresp, err := client.Policy().CreateRateLimitPolicy(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/policy/createratelimitpolicy\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.policy.v1 import policy_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 = policy_pb2.CreateRateLimitPolicyRequest()\ntry:\n    result = client.policy.create_rate_limit_policy(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.policy.createRateLimitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies create --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"rate_limit_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies","slug":"create-a-rate-limit-policy"}

Get a rate-limit policy

Changed in v0.8.0 (new features): A project or API key rate-limit policy can now limit requests per minute, requests per hour and tokens per minute beside tokens per hour, in any mix. Existing per-hour values stay. A refused request gets a 429 naming the policy and its window when the data plane can tell which policy set the limit. UpdateRateLimitPolicy removes one limit through clear_dimensions, GetEffectivePolicy names the dimension of each entry, and period has no effect. count_tokens calls count against no rate limit.

Changed in v0.7.0 (new features): A rate-limit policy now carries a display_name, the public label a caller will see when that limit refuses a request. Existing policies take their name as the label, and a policy created without one does the same, so a platform operator only sets it when the name is not meant for callers. The label is stored and returned for now; the refusal body that prints it is still to come.

What it does: Returns a single rate-limit policy by id. The period field has no effect on enforcement.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to fetch.
customer_idnoOptional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"].
project_idnoOptional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"].

Response fields:

FieldRequiredDescription
rate_limit_policynoThe requested policy.
{"signatures":{"go":"func (x *PolicyClient) GetRateLimitPolicy(ctx context.Context, req *policyv1.GetRateLimitPolicyRequest) (*policyv1.GetRateLimitPolicyResponse, error)","python":"get_rate_limit_policy(req: policy_pb2.GetRateLimitPolicyRequest) -\u003e GetRateLimitPolicyResponse","typescript":"getRateLimitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetRateLimitPolicyRequestSchema\u003e): Promise\u003cGetRateLimitPolicyResponse\u003e","cli":"tare api policy rate-limit-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetRateLimitPolicyRequest{}\n\n\tresp, err := client.Policy().GetRateLimitPolicy(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/policy/getratelimitpolicy\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.policy.v1 import policy_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 = policy_pb2.GetRateLimitPolicyRequest()\ntry:\n    result = client.policy.get_rate_limit_policy(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.policy.getRateLimitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies/{id}","slug":"get-a-rate-limit-policy"}

List rate-limit policies

Changed in v0.8.0 (new features): A project or API key rate-limit policy can now limit requests per minute, requests per hour and tokens per minute beside tokens per hour, in any mix. Existing per-hour values stay. A refused request gets a 429 naming the policy and its window when the data plane can tell which policy set the limit. UpdateRateLimitPolicy removes one limit through clear_dimensions, GetEffectivePolicy names the dimension of each entry, and period has no effect. count_tokens calls count against no rate limit.

Changed in v0.7.0 (new features): A rate-limit policy now carries a display_name, the public label a caller will see when that limit refuses a request. Existing policies take their name as the label, and a policy created without one does the same, so a platform operator only sets it when the name is not meant for callers. The label is stored and returned for now; the refusal body that prints it is still to come.

What it does: Returns rate-limit policies matching the specified filters. The period field has no effect on enforcement.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
searchnoOptional substring search on policy name.
scope_typesnoFilter to policies with these scope types.
statusesnoFilter to policies in these statuses.
api_key_idnoFilter to policies targeting this api_key_id.
customer_idnoOptional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"].
project_idnoOptional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"].

Response fields:

FieldRequiredDescription
rate_limit_policiesnoPolicies matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListRateLimitPolicies(ctx context.Context, req *policyv1.ListRateLimitPoliciesRequest) (*policyv1.ListRateLimitPoliciesResponse, error)","python":"list_rate_limit_policies(req: policy_pb2.ListRateLimitPoliciesRequest) -\u003e ListRateLimitPoliciesResponse","typescript":"listRateLimitPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListRateLimitPoliciesRequestSchema\u003e): Promise\u003cListRateLimitPoliciesResponse\u003e","cli":"tare api policy rate-limit-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListRateLimitPoliciesRequest{}\n\n\tresp, err := client.Policy().ListRateLimitPolicies(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/policy/listratelimitpolicies\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.policy.v1 import policy_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 = policy_pb2.ListRateLimitPoliciesRequest()\ntry:\n    result = client.policy.list_rate_limit_policies(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.policy.listRateLimitPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies","slug":"list-rate-limit-policies"}

Upsert a fallback policy

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (behaviour changes): Saving fallback chain entries requires enabled models and providers. Project and API-key policies restrict models only when their effective project has assignments; projects without assignments allow all enabled models. API-key policies require a live project on their client group. Organization-wide policies need no assignments. BOUND model allow-lists are not validated.

Changed in v0.9.0 (behaviour changes): Saving a per-key fallback policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the key's project. Keys in the default project are not limited this way.

Changed in v0.9.0 (new features): The owner of an API key can set and turn off the fallback and traffic split policies of that key, without a project role.

Changed in v0.9.0 (bug fixes): Listing policies by target_key_id finds the per-key fallback and traffic split policies saved in the Developer Console, and those of a disabled key. The first per-key fallback policy saved through the API no longer fails for a key that never had one.

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.6.0 (behaviour changes): A fallback-policy write sent with a project is now refused unless its target stays inside that project: the organization-wide default (a CUSTOMER target), tag-targeted legacy policies, and any key or project outside it are rejected, even for an organization administrator. Writes sent without a project keep working as before.

Changed in v0.6.0 (behaviour changes): A fallback policy now rejects an unsupported retry_on value with a clear message instead of silently storing it. An existing value with an unknown token reads back empty, meaning the default retry set applies.

Changed in v0.6.0 (new features): Project owners can now manage fallback policies for their own project: creating, updating, deleting, activating and deactivating project- and API-key-scoped policies inside a project they own needs only the project owner's own grants. A request routed through a project may only target that project -- a key or project outside it, or the organization-wide default, is refused, and the organization-wide default keeps its organization-level administration.

Changed in v0.6.0 (bug fixes): A fallback or traffic-split policy write with a missing or unrecognised target_scope_type now explains that unknown JSON names are ignored and names the target id fields to check. A project-routed PROJECT-scope write with no target_project_id now returns INVALID_ARGUMENT naming the field, instead of PERMISSION_DENIED.

Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.

Changed in v0.5.0 (bug fixes): Fallback policies now keep independent ordered entries for each protected model and resolve project and organization policies, plus API-key policies, in the documented precedence order. Full-set updates converge on replay, remove omitted entries, and treat an explicit empty set as a deactivated override while preserving legacy fallback-chain aliases.

What it does: Replaces the complete set of fallback entries for one organization, project, or API-key target. entries is authoritative: omitted protected models are removed, and an empty set deactivates the target. Release 1 precedence is API key > project > organization/customer; tag targets are reporting-only and cannot be created by this operation. Eligible retry categories are timeout, rate-limit/capacity, and server error. Malformed requests, content refusals, rejected credentials, and other non-eligible client failures do not advance the ordered list. Effective responses and request logs identify the serving model and the source scope/policy. The public names are FallbackPolicy, fallback-policies, entries, and fallback_models; FallbackChainPolicy and chain remain read/write aliases for legacy clients.

Request fields:

FieldRequiredDescription
fallback_policyyesComplete desired policy state for the target.
customer_idyesFraser organization/tenant that owns the target.
project_idnoRequired only for PROJECT scope.

Response fields:

FieldRequiredDescription
fallback_policynoThe committed canonical policy, including the complete grouped entry set.
{"signatures":{"go":"func (x *PolicyClient) UpsertFallbackPolicy(ctx context.Context, req *policyv1.UpsertFallbackPolicyRequest) (*policyv1.UpsertFallbackPolicyResponse, error)","python":"upsert_fallback_policy(req: policy_pb2.UpsertFallbackPolicyRequest) -\u003e UpsertFallbackPolicyResponse","typescript":"upsertFallbackPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpsertFallbackPolicyRequestSchema\u003e): Promise\u003cUpsertFallbackPolicyResponse\u003e","cli":"tare api policy fallback-policies upsert --fallback-policy $FALLBACK_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-policies:upsert\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpsertFallbackPolicyRequest{}\n\n\tresp, err := client.Policy().UpsertFallbackPolicy(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/policy/upsertfallbackpolicy\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.policy.v1 import policy_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 = policy_pb2.UpsertFallbackPolicyRequest()\ntry:\n    result = client.policy.upsert_fallback_policy(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.policy.upsertFallbackPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-policies upsert --fallback-policy $FALLBACK_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-policies:upsert\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-policies:upsert","slug":"upsert-a-fallback-policy"}

Create a fallback chain policy

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (behaviour changes): Saving fallback chain entries requires enabled models and providers. Project and API-key policies restrict models only when their effective project has assignments; projects without assignments allow all enabled models. API-key policies require a live project on their client group. Organization-wide policies need no assignments. BOUND model allow-lists are not validated.

Changed in v0.6.0 (behaviour changes): A fallback-policy write sent with a project is now refused unless its target stays inside that project: the organization-wide default (a CUSTOMER target), tag-targeted legacy policies, and any key or project outside it are rejected, even for an organization administrator. Writes sent without a project keep working as before.

Changed in v0.6.0 (new features): Project owners can now manage fallback policies for their own project: creating, updating, deleting, activating and deactivating project- and API-key-scoped policies inside a project they own needs only the project owner's own grants. A request routed through a project may only target that project -- a key or project outside it, or the organization-wide default, is refused, and the organization-wide default keeps its organization-level administration.

Changed in v0.6.0 (bug fixes): Project-scoped traffic-split, fallback-chain and attribute routing policies now create and update successfully when no tag selector is supplied.

Changed in v0.6.0 (bug fixes): A fallback or traffic-split policy write with a missing or unrecognised target_scope_type now explains that unknown JSON names are ignored and names the target id fields to check. A project-routed PROJECT-scope write with no target_project_id now returns INVALID_ARGUMENT naming the field, instead of PERMISSION_DENIED.

Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.

Request fields:

FieldRequiredDescription
fallback_chain_policyyesRequired: policy to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note.
project_idnoRequired only for PROJECT scope. Omit for CUSTOMER and API_KEY scope; the server validates the target's tenant ownership.

Response fields:

FieldRequiredDescription
fallback_chain_policynoThe created policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateFallbackChainPolicy(ctx context.Context, req *policyv1.CreateFallbackChainPolicyRequest) (*policyv1.CreateFallbackChainPolicyResponse, error)","python":"create_fallback_chain_policy(req: policy_pb2.CreateFallbackChainPolicyRequest) -\u003e CreateFallbackChainPolicyResponse","typescript":"createFallbackChainPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateFallbackChainPolicyRequestSchema\u003e): Promise\u003cCreateFallbackChainPolicyResponse\u003e","cli":"tare api policy fallback-chain-policies create --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_chain_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateFallbackChainPolicyRequest{}\n\n\tresp, err := client.Policy().CreateFallbackChainPolicy(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/policy/createfallbackchainpolicy\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.policy.v1 import policy_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 = policy_pb2.CreateFallbackChainPolicyRequest()\ntry:\n    result = client.policy.create_fallback_chain_policy(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.policy.createFallbackChainPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies create --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_chain_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies","slug":"create-a-fallback-chain-policy"}

Get a fallback chain policy

Changed in v0.9.0 (behaviour changes): A fallback policy saved before retry conditions were configurable reads back the five conditions the gateway applies to it, timeout,rate-limit,server-error,connect-failure,overloaded, instead of its stored retry_on. Saving that value back keeps the same retries, and changing retry_on now takes effect for such a policy.

Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.

What it does: Returns a single fallback chain policy by id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to fetch.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering.
project_idnoOptional: project scope for future project-scoped filtering.

Response fields:

FieldRequiredDescription
fallback_chain_policynoThe requested policy.
{"signatures":{"go":"func (x *PolicyClient) GetFallbackChainPolicy(ctx context.Context, req *policyv1.GetFallbackChainPolicyRequest) (*policyv1.GetFallbackChainPolicyResponse, error)","python":"get_fallback_chain_policy(req: policy_pb2.GetFallbackChainPolicyRequest) -\u003e GetFallbackChainPolicyResponse","typescript":"getFallbackChainPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetFallbackChainPolicyRequestSchema\u003e): Promise\u003cGetFallbackChainPolicyResponse\u003e","cli":"tare api policy fallback-chain-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetFallbackChainPolicyRequest{}\n\n\tresp, err := client.Policy().GetFallbackChainPolicy(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/policy/getfallbackchainpolicy\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.policy.v1 import policy_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 = policy_pb2.GetFallbackChainPolicyRequest()\ntry:\n    result = client.policy.get_fallback_chain_policy(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.policy.getFallbackChainPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/fallback-chain-policies/{id}","slug":"get-a-fallback-chain-policy"}

List fallback chain policies

Changed in v0.11.0 (new features): ListApiKeys lists the keys of one organization or project, with status, owner, text and ID filters, a filter for the keys that can hold their own fallback policy (override_targetable_only), sorting, counts and the key owners. Keys show their client, disabled state and deletion time. A fallback policy that targets a key shows the project of that key. A management key bound to an organization gets PERMISSION_DENIED for another organization's keys.

Changed in v0.10.0 (behaviour changes): Listing fallback or traffic-split policies for one API key now returns them only to the key's owner, the owners of its project, organization admins and admin keys. Other users and non-admin keys get a permission error.

Changed in v0.9.0 (behaviour changes): A fallback policy saved before retry conditions were configurable reads back the five conditions the gateway applies to it, timeout,rate-limit,server-error,connect-failure,overloaded, instead of its stored retry_on. Saving that value back keeps the same retries, and changing retry_on now takes effect for such a policy.

Changed in v0.9.0 (behaviour changes): Listing fallback or traffic split policies without a target now also returns the per-key policies saved in the Developer Console, so the Admin Console's Fallback Policies page shows them too. That page does not load when there are more than 5,000 fallback policies.

Changed in v0.9.0 (bug fixes): Listing policies by target_key_id finds the per-key fallback and traffic split policies saved in the Developer Console, and those of a disabled key. The first per-key fallback policy saved through the API no longer fails for a key that never had one.

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.

What it does: Returns fallback chain policies matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
target_scope_typesnoFilter to policies with these target scope types.
statusesnoFilter to policies in these statuses.
target_key_idnoFilter to policies targeting this target_key_id.
target_project_idnoFilter to policies targeting this target_project_id.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering.
project_idnoOptional: project scope for future project-scoped filtering.

Response fields:

FieldRequiredDescription
fallback_chain_policiesnoPolicies matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListFallbackChainPolicies(ctx context.Context, req *policyv1.ListFallbackChainPoliciesRequest) (*policyv1.ListFallbackChainPoliciesResponse, error)","python":"list_fallback_chain_policies(req: policy_pb2.ListFallbackChainPoliciesRequest) -\u003e ListFallbackChainPoliciesResponse","typescript":"listFallbackChainPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListFallbackChainPoliciesRequestSchema\u003e): Promise\u003cListFallbackChainPoliciesResponse\u003e","cli":"tare api policy fallback-chain-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListFallbackChainPoliciesRequest{}\n\n\tresp, err := client.Policy().ListFallbackChainPolicies(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/policy/listfallbackchainpolicies\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.policy.v1 import policy_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 = policy_pb2.ListFallbackChainPoliciesRequest()\ntry:\n    result = client.policy.list_fallback_chain_policies(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.policy.listFallbackChainPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/fallback-chain-policies","slug":"list-fallback-chain-policies"}

Update a rate-limit policy

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.8.0 (new features): A project or API key rate-limit policy can now limit requests per minute, requests per hour and tokens per minute beside tokens per hour, in any mix. Existing per-hour values stay. A refused request gets a 429 naming the policy and its window when the data plane can tell which policy set the limit. UpdateRateLimitPolicy removes one limit through clear_dimensions, GetEffectivePolicy names the dimension of each entry, and period has no effect. count_tokens calls count against no rate limit.

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.7.0 (new features): A rate-limit policy now carries a display_name, the public label a caller will see when that limit refuses a request. Existing policies take their name as the label, and a policy created without one does the same, so a platform operator only sets it when the name is not meant for callers. The label is stored and returned for now; the refusal body that prints it is still to come.

Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.

What it does: Updates mutable rate-limit policy fields. Omitted/empty scalar fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. The policy id must be set inside the rate_limit_policy field. To remove a dimension, list it in clear_dimensions. A policy sets any mix of six limits, and each one applies on its own. - input_tokens_per_hour: input (prompt) tokens per rolling hour. - output_tokens_per_hour: output (completion) tokens per rolling hour. - total_tokens_per_hour: input plus output tokens per rolling hour. This is the "tokens per hour" limit. - total_tokens_per_minute: input plus output tokens per rolling minute. - requests_per_minute: requests per rolling minute. Each request counts 1 when it arrives. - requests_per_hour: requests per rolling hour. requests_per_minute, requests_per_hour and total_tokens_per_minute are accepted only with scope_type PROJECT or API_KEY and action BLOCK. The server refuses them on any other scope or action with InvalidArgument. Every dimension that is set must be between 1 and 1,000,000,000. The server refuses any other value with InvalidArgument. A project-scope limit is counted for each API key in the project on its own, not shared across the project. The period field has no effect: the server stores and returns it, and each dimension's window comes from the dimension's name. The server refuses the update with FailedPrecondition when it sets one of the three newer dimensions and a data plane serving the target project reports a build older than 0.8.0, or no build.

Request fields:

FieldRequiredDescription
rate_limit_policyyesRequired: policy to update. rate_limit_policy.id must be set. Partial update semantics: omitted/empty scalar fields leave the existing value untouched; enum fields set to *_UNSPECIFIED leave the existing value untouched.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller.
clear_dimensionsnoDimensions to remove from the stored policy. The server sets each listed dimension to unset. Naming a dimension here and also setting it in rate_limit_policy.limit is InvalidArgument. Clearing every dimension the policy has is InvalidArgument, because a policy needs at least one.

Response fields:

FieldRequiredDescription
rate_limit_policynoThe updated policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) UpdateRateLimitPolicy(ctx context.Context, req *policyv1.UpdateRateLimitPolicyRequest) (*policyv1.UpdateRateLimitPolicyResponse, error)","python":"update_rate_limit_policy(req: policy_pb2.UpdateRateLimitPolicyRequest) -\u003e UpdateRateLimitPolicyResponse","typescript":"updateRateLimitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateRateLimitPolicyRequestSchema\u003e): Promise\u003cUpdateRateLimitPolicyResponse\u003e","cli":"tare api policy rate-limit-policies update --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"rate_limit_policy\": {},\n    \"clear_dimensions\": []\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateRateLimitPolicyRequest{}\n\n\tresp, err := client.Policy().UpdateRateLimitPolicy(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/policy/updateratelimitpolicy\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.policy.v1 import policy_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 = policy_pb2.UpdateRateLimitPolicyRequest()\ntry:\n    result = client.policy.update_rate_limit_policy(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.policy.updateRateLimitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies update --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"rate_limit_policy\": {},\n    \"clear_dimensions\": []\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{rate_limit_policy.id}","slug":"update-a-rate-limit-policy"}

Update a fallback chain policy

Changed in v0.10.0 (behaviour changes): Updating a fallback policy is refused with INVALID_ARGUMENT when a changed chain is sent alone for a policy with several entries, or when chain and entries are both changed so they disagree. Before, the first merged the entries into one and the second saved entries.

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.10.0 (bug fixes): Editing chain in a fallback policy you read back now saves; before, the entries sent with it won and the edit was ignored.

Changed in v0.9.0 (behaviour changes): Saving fallback chain entries requires enabled models and providers. Project and API-key policies restrict models only when their effective project has assignments; projects without assignments allow all enabled models. API-key policies require a live project on their client group. Organization-wide policies need no assignments. BOUND model allow-lists are not validated.

Changed in v0.9.0 (behaviour changes): A fallback policy saved before retry conditions were configurable reads back the five conditions the gateway applies to it, timeout,rate-limit,server-error,connect-failure,overloaded, instead of its stored retry_on. Saving that value back keeps the same retries, and changing retry_on now takes effect for such a policy.

Changed in v0.9.0 (behaviour changes): Saving a per-key fallback policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the key's project. Keys in the default project are not limited this way.

Changed in v0.6.0 (behaviour changes): A fallback-policy write sent with a project is now refused unless its target stays inside that project: the organization-wide default (a CUSTOMER target), tag-targeted legacy policies, and any key or project outside it are rejected, even for an organization administrator. Writes sent without a project keep working as before.

Changed in v0.6.0 (new features): Project owners can now manage fallback policies for their own project: creating, updating, deleting, activating and deactivating project- and API-key-scoped policies inside a project they own needs only the project owner's own grants. A request routed through a project may only target that project -- a key or project outside it, or the organization-wide default, is refused, and the organization-wide default keeps its organization-level administration.

Changed in v0.6.0 (bug fixes): Project-scoped traffic-split, fallback-chain and attribute routing policies now create and update successfully when no tag selector is supplied.

Changed in v0.6.0 (bug fixes): A fallback or traffic-split policy write with a missing or unrecognised target_scope_type now explains that unknown JSON names are ignored and names the target id fields to check. A project-routed PROJECT-scope write with no target_project_id now returns INVALID_ARGUMENT naming the field, instead of PERMISSION_DENIED.

Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.

What it does: Updates mutable fallback chain policy fields. Omitted/empty scalar string fields leave the existing value untouched. The policy id must be set inside the fallback_chain_policy field.

Request fields:

FieldRequiredDescription
fallback_chain_policyyesRequired: policy to update. fallback_chain_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idnoRequired only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope.

Response fields:

FieldRequiredDescription
fallback_chain_policynoThe updated policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) UpdateFallbackChainPolicy(ctx context.Context, req *policyv1.UpdateFallbackChainPolicyRequest) (*policyv1.UpdateFallbackChainPolicyResponse, error)","python":"update_fallback_chain_policy(req: policy_pb2.UpdateFallbackChainPolicyRequest) -\u003e UpdateFallbackChainPolicyResponse","typescript":"updateFallbackChainPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateFallbackChainPolicyRequestSchema\u003e): Promise\u003cUpdateFallbackChainPolicyResponse\u003e","cli":"tare api policy fallback-chain-policies update --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_chain_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateFallbackChainPolicyRequest{}\n\n\tresp, err := client.Policy().UpdateFallbackChainPolicy(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/policy/updatefallbackchainpolicy\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.policy.v1 import policy_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 = policy_pb2.UpdateFallbackChainPolicyRequest()\ntry:\n    result = client.policy.update_fallback_chain_policy(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.policy.updateFallbackChainPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies update --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"fallback_chain_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{fallback_chain_policy.id}","slug":"update-a-fallback-chain-policy"}

Delete a rate-limit policy

What it does: Deletes a rate-limit policy.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to delete.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller.
{"signatures":{"go":"func (x *PolicyClient) DeleteRateLimitPolicy(ctx context.Context, req *policyv1.DeleteRateLimitPolicyRequest) (*policyv1.DeleteRateLimitPolicyResponse, error)","python":"delete_rate_limit_policy(req: policy_pb2.DeleteRateLimitPolicyRequest) -\u003e DeleteRateLimitPolicyResponse","typescript":"deleteRateLimitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteRateLimitPolicyRequestSchema\u003e): Promise\u003cDeleteRateLimitPolicyResponse\u003e","cli":"tare api policy rate-limit-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteRateLimitPolicyRequest{}\n\n\tresp, err := client.Policy().DeleteRateLimitPolicy(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/policy/deleteratelimitpolicy\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.policy.v1 import policy_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 = policy_pb2.DeleteRateLimitPolicyRequest()\ntry:\n    result = client.policy.delete_rate_limit_policy(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.policy.deleteRateLimitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{id}","slug":"delete-a-rate-limit-policy"}

Delete a fallback chain policy

Changed in v0.6.0 (behaviour changes): A fallback-policy write sent with a project is now refused unless its target stays inside that project: the organization-wide default (a CUSTOMER target), tag-targeted legacy policies, and any key or project outside it are rejected, even for an organization administrator. Writes sent without a project keep working as before.

Changed in v0.6.0 (new features): Project owners can now manage fallback policies for their own project: creating, updating, deleting, activating and deactivating project- and API-key-scoped policies inside a project they own needs only the project owner's own grants. A request routed through a project may only target that project -- a key or project outside it, or the organization-wide default, is refused, and the organization-wide default keeps its organization-level administration.

What it does: Deletes a fallback chain policy.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to delete.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idnoRequired only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope.
target_key_idnoRequired only by the API_KEY route; used to identify the affected key.
{"signatures":{"go":"func (x *PolicyClient) DeleteFallbackChainPolicy(ctx context.Context, req *policyv1.DeleteFallbackChainPolicyRequest) (*policyv1.DeleteFallbackChainPolicyResponse, error)","python":"delete_fallback_chain_policy(req: policy_pb2.DeleteFallbackChainPolicyRequest) -\u003e DeleteFallbackChainPolicyResponse","typescript":"deleteFallbackChainPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteFallbackChainPolicyRequestSchema\u003e): Promise\u003cDeleteFallbackChainPolicyResponse\u003e","cli":"tare api policy fallback-chain-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteFallbackChainPolicyRequest{}\n\n\tresp, err := client.Policy().DeleteFallbackChainPolicy(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/policy/deletefallbackchainpolicy\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.policy.v1 import policy_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 = policy_pb2.DeleteFallbackChainPolicyRequest()\ntry:\n    result = client.policy.delete_fallback_chain_policy(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.policy.deleteFallbackChainPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{id}","slug":"delete-a-fallback-chain-policy"}

Set rate-limit policy status

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.

What it does: Toggles a rate-limit policy's active/inactive state (is_active).

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
statusyesRequired: new operational status for the policy.
customer_idyesRequired: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller.
project_idyesRequired: project that owns the target policy. Read by the project_owner persona to authorize the caller.

Response fields:

FieldRequiredDescription
rate_limit_policynoThe policy with the updated status.
{"signatures":{"go":"func (x *PolicyClient) SetRateLimitPolicyStatus(ctx context.Context, req *policyv1.SetRateLimitPolicyStatusRequest) (*policyv1.SetRateLimitPolicyStatusResponse, error)","python":"set_rate_limit_policy_status(req: policy_pb2.SetRateLimitPolicyStatusRequest) -\u003e SetRateLimitPolicyStatusResponse","typescript":"setRateLimitPolicyStatus(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetRateLimitPolicyStatusRequestSchema\u003e): Promise\u003cSetRateLimitPolicyStatusResponse\u003e","cli":"tare api policy rate-limit-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetRateLimitPolicyStatusRequest{}\n\n\tresp, err := client.Policy().SetRateLimitPolicyStatus(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/policy/setratelimitpolicystatus\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.policy.v1 import policy_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 = policy_pb2.SetRateLimitPolicyStatusRequest()\ntry:\n    result = client.policy.set_rate_limit_policy_status(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.policy.setRateLimitPolicyStatus(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{id}/status","slug":"set-rate-limit-policy-status"}

Set fallback chain policy status

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (behaviour changes): Saving a per-key fallback policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the key's project. Keys in the default project are not limited this way.

Changed in v0.9.0 (new features): The owner of an API key can set and turn off the fallback and traffic split policies of that key, without a project role.

Changed in v0.6.0 (behaviour changes): A fallback-policy write sent with a project is now refused unless its target stays inside that project: the organization-wide default (a CUSTOMER target), tag-targeted legacy policies, and any key or project outside it are rejected, even for an organization administrator. Writes sent without a project keep working as before.

Changed in v0.6.0 (new features): Project owners can now manage fallback policies for their own project: creating, updating, deleting, activating and deactivating project- and API-key-scoped policies inside a project they own needs only the project owner's own grants. A request routed through a project may only target that project -- a key or project outside it, or the organization-wide default, is refused, and the organization-wide default keeps its organization-level administration.

What it does: Toggles a fallback chain policy's active/inactive state (is_active).

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
statusyesRequired: new operational status for the policy.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idnoRequired only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope.
target_key_idnoRequired only by the API_KEY route; used to identify the affected key.

Response fields:

FieldRequiredDescription
fallback_chain_policynoThe policy with the updated status.
{"signatures":{"go":"func (x *PolicyClient) SetFallbackChainPolicyStatus(ctx context.Context, req *policyv1.SetFallbackChainPolicyStatusRequest) (*policyv1.SetFallbackChainPolicyStatusResponse, error)","python":"set_fallback_chain_policy_status(req: policy_pb2.SetFallbackChainPolicyStatusRequest) -\u003e SetFallbackChainPolicyStatusResponse","typescript":"setFallbackChainPolicyStatus(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetFallbackChainPolicyStatusRequestSchema\u003e): Promise\u003cSetFallbackChainPolicyStatusResponse\u003e","cli":"tare api policy fallback-chain-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\",\n    \"target_key_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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetFallbackChainPolicyStatusRequest{}\n\n\tresp, err := client.Policy().SetFallbackChainPolicyStatus(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/policy/setfallbackchainpolicystatus\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.policy.v1 import policy_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 = policy_pb2.SetFallbackChainPolicyStatusRequest()\ntry:\n    result = client.policy.set_fallback_chain_policy_status(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.policy.setFallbackChainPolicyStatus(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy fallback-chain-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\",\n    \"target_key_id\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{id}/status","slug":"set-fallback-chain-policy-status"}

Get would-have-limited analytics for a rate-limit policy

What it does: Computes a "would-have-limited" analytics preview for a MONITOR-action rate-limit policy (fraser#5446 pass 2, item 4.4 / ADR-036 R2 Option B): for each hour in the lookback window, it sums the policy's audience (the same scope resolution the min-clamp resolver uses -- key / tag / project / system) from the existing usage rollups (usage_hourly_rollups) and reports how many of those hours would have breached the policy's triplet ceiling, had the policy been enforced. This is NOT true shadow-mode enforcement (no per-request evaluation, no sub-hour granularity) -- it is a rollup-derived retrospective estimate, intended to help an operator decide whether flipping a MONITOR policy to BLOCK is safe (see the Flow-1 monitor->active flip, fraser#5448). Rejects a BLOCK-action policy's id with FailedPrecondition: a BLOCK policy is already actually enforced by the min-clamp resolver, so a retrospective "would it have limited" estimate is not meaningful for it.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the (MONITOR-action) rate-limit policy to evaluate.
customer_idnoOptional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"].
project_idnoOptional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"].
lookback_hoursnoOptional: lookback window in hours, ending now. Defaults to 72 hours server-side when unset or 0; clamped to the usage_hourly_rollups retention window (rollups older than retention have already been deleted, so a larger request silently evaluates fewer hours than asked).

Response fields:

FieldRequiredDescription
analyticsnoundocumented
{"signatures":{"go":"func (x *PolicyClient) GetRateLimitPolicyAnalytics(ctx context.Context, req *policyv1.GetRateLimitPolicyAnalyticsRequest) (*policyv1.GetRateLimitPolicyAnalyticsResponse, error)","python":"get_rate_limit_policy_analytics(req: policy_pb2.GetRateLimitPolicyAnalyticsRequest) -\u003e GetRateLimitPolicyAnalyticsResponse","typescript":"getRateLimitPolicyAnalytics(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetRateLimitPolicyAnalyticsRequestSchema\u003e): Promise\u003cGetRateLimitPolicyAnalyticsResponse\u003e","cli":"tare api policy rate-limit-policies analytics \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H.../analytics\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetRateLimitPolicyAnalyticsRequest{}\n\n\tresp, err := client.Policy().GetRateLimitPolicyAnalytics(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/policy/getratelimitpolicyanalytics\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.policy.v1 import policy_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 = policy_pb2.GetRateLimitPolicyAnalyticsRequest()\ntry:\n    result = client.policy.get_rate_limit_policy_analytics(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.policy.getRateLimitPolicyAnalytics(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy rate-limit-policies analytics \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H.../analytics\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies/{id}/analytics","slug":"get-would-have-limited-analytics-for-a-rate-limit-policy"}

Create a traffic split policy

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (new features): The owner of an API key can set and turn off the fallback and traffic split policies of that key, without a project role.

Changed in v0.9.0 (new features): Traffic split policies can target one API key, and hold one weighted split for each primary model in the new entries field. Each entry needs a different primary model name. Create, update and status calls also work on a path without a project. A per-key split is refused when a model or its provider is not available to the key's project, except in the default project. A model can have weight 0 if another has more.

Changed in v0.6.0 (bug fixes): Project-scoped traffic-split, fallback-chain and attribute routing policies now create and update successfully when no tag selector is supplied.

Changed in v0.6.0 (bug fixes): A fallback or traffic-split policy write with a missing or unrecognised target_scope_type now explains that unknown JSON names are ignored and names the target id fields to check. A project-routed PROJECT-scope write with no target_project_id now returns INVALID_ARGUMENT naming the field, instead of PERMISSION_DENIED.

What it does: Creates a new traffic-split policy scoped to a key, tag selector, or project (fraser#5447, item 4.2). A KEY policy is stored on the key's effective client, one per client: a second create returns ALREADY_EXISTS. The owner of a key can create its KEY policy without project_id (fraser#10611).

Request fields:

FieldRequiredDescription
traffic_split_policyyesRequired: policy to create. id must be absent or empty (server-assigned).
customer_idyesRequired: customer (tenant) that will own the created policy.
project_idnoProject that will own the created policy. A KEY policy may omit it; when set, the key must belong to this project.

Response fields:

FieldRequiredDescription
traffic_split_policynoThe created policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateTrafficSplitPolicy(ctx context.Context, req *policyv1.CreateTrafficSplitPolicyRequest) (*policyv1.CreateTrafficSplitPolicyResponse, error)","python":"create_traffic_split_policy(req: policy_pb2.CreateTrafficSplitPolicyRequest) -\u003e CreateTrafficSplitPolicyResponse","typescript":"createTrafficSplitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateTrafficSplitPolicyRequestSchema\u003e): Promise\u003cCreateTrafficSplitPolicyResponse\u003e","cli":"tare api policy traffic-split-policies create --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"traffic_split_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateTrafficSplitPolicyRequest{}\n\n\tresp, err := client.Policy().CreateTrafficSplitPolicy(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/policy/createtrafficsplitpolicy\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.policy.v1 import policy_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 = policy_pb2.CreateTrafficSplitPolicyRequest()\ntry:\n    result = client.policy.create_traffic_split_policy(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.policy.createTrafficSplitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies create --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"traffic_split_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies","slug":"create-a-traffic-split-policy"}

Get a traffic split policy

Changed in v0.9.0 (behaviour changes): Traffic split policies now read back with entries as well as split. An update that sends both keeps whichever differs from the saved policy, so editing only split in a read-back still works; changing both so they disagree is refused.

Changed in v0.9.0 (new features): Traffic split policies can target one API key, and hold one weighted split for each primary model in the new entries field. Each entry needs a different primary model name. Create, update and status calls also work on a path without a project. A per-key split is refused when a model or its provider is not available to the key's project, except in the default project. A model can have weight 0 if another has more.

What it does: Returns a single traffic split policy by id.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to fetch.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering.
project_idnoOptional: project scope for future project-scoped filtering.

Response fields:

FieldRequiredDescription
traffic_split_policynoThe requested policy.
{"signatures":{"go":"func (x *PolicyClient) GetTrafficSplitPolicy(ctx context.Context, req *policyv1.GetTrafficSplitPolicyRequest) (*policyv1.GetTrafficSplitPolicyResponse, error)","python":"get_traffic_split_policy(req: policy_pb2.GetTrafficSplitPolicyRequest) -\u003e GetTrafficSplitPolicyResponse","typescript":"getTrafficSplitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetTrafficSplitPolicyRequestSchema\u003e): Promise\u003cGetTrafficSplitPolicyResponse\u003e","cli":"tare api policy traffic-split-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetTrafficSplitPolicyRequest{}\n\n\tresp, err := client.Policy().GetTrafficSplitPolicy(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/policy/gettrafficsplitpolicy\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.policy.v1 import policy_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 = policy_pb2.GetTrafficSplitPolicyRequest()\ntry:\n    result = client.policy.get_traffic_split_policy(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.policy.getTrafficSplitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/traffic-split-policies/{id}","slug":"get-a-traffic-split-policy"}

List traffic split policies

Changed in v0.10.0 (behaviour changes): Listing fallback or traffic-split policies for one API key now returns them only to the key's owner, the owners of its project, organization admins and admin keys. Other users and non-admin keys get a permission error.

Changed in v0.9.0 (behaviour changes): Traffic split policies now read back with entries as well as split. An update that sends both keeps whichever differs from the saved policy, so editing only split in a read-back still works; changing both so they disagree is refused.

Changed in v0.9.0 (behaviour changes): Listing fallback or traffic split policies without a target now also returns the per-key policies saved in the Developer Console, so the Admin Console's Fallback Policies page shows them too. That page does not load when there are more than 5,000 fallback policies.

Changed in v0.9.0 (new features): Traffic split policies can target one API key, and hold one weighted split for each primary model in the new entries field. Each entry needs a different primary model name. Create, update and status calls also work on a path without a project. A per-key split is refused when a model or its provider is not available to the key's project, except in the default project. A model can have weight 0 if another has more.

Changed in v0.9.0 (bug fixes): Listing policies by target_key_id finds the per-key fallback and traffic split policies saved in the Developer Console, and those of a disabled key. The first per-key fallback policy saved through the API no longer fails for a key that never had one.

What it does: Returns traffic split policies matching the specified filters.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
target_scope_typesnoFilter to policies with these target scope types.
statusesnoFilter to policies in these statuses.
target_key_idnoFilter to policies targeting this target_key_id.
target_project_idnoFilter to policies targeting this target_project_id.
customer_idnoOptional: customer (tenant) scope for future project-scoped filtering.
project_idnoOptional: project scope for future project-scoped filtering.

Response fields:

FieldRequiredDescription
traffic_split_policiesnoPolicies matching the request filters, one page's worth.
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListTrafficSplitPolicies(ctx context.Context, req *policyv1.ListTrafficSplitPoliciesRequest) (*policyv1.ListTrafficSplitPoliciesResponse, error)","python":"list_traffic_split_policies(req: policy_pb2.ListTrafficSplitPoliciesRequest) -\u003e ListTrafficSplitPoliciesResponse","typescript":"listTrafficSplitPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListTrafficSplitPoliciesRequestSchema\u003e): Promise\u003cListTrafficSplitPoliciesResponse\u003e","cli":"tare api policy traffic-split-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListTrafficSplitPoliciesRequest{}\n\n\tresp, err := client.Policy().ListTrafficSplitPolicies(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/policy/listtrafficsplitpolicies\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.policy.v1 import policy_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 = policy_pb2.ListTrafficSplitPoliciesRequest()\ntry:\n    result = client.policy.list_traffic_split_policies(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.policy.listTrafficSplitPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/traffic-split-policies","slug":"list-traffic-split-policies"}

Update a traffic split policy

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (behaviour changes): Traffic split policies now read back with entries as well as split. An update that sends both keeps whichever differs from the saved policy, so editing only split in a read-back still works; changing both so they disagree is refused.

Changed in v0.9.0 (new features): The owner of an API key can set and turn off the fallback and traffic split policies of that key, without a project role.

Changed in v0.9.0 (new features): Traffic split policies can target one API key, and hold one weighted split for each primary model in the new entries field. Each entry needs a different primary model name. Create, update and status calls also work on a path without a project. A per-key split is refused when a model or its provider is not available to the key's project, except in the default project. A model can have weight 0 if another has more.

Changed in v0.6.0 (bug fixes): Project-scoped traffic-split, fallback-chain and attribute routing policies now create and update successfully when no tag selector is supplied.

Changed in v0.6.0 (bug fixes): A fallback or traffic-split policy write with a missing or unrecognised target_scope_type now explains that unknown JSON names are ignored and names the target id fields to check. A project-routed PROJECT-scope write with no target_project_id now returns INVALID_ARGUMENT naming the field, instead of PERMISSION_DENIED.

What it does: Updates mutable traffic split policy fields. Omitted/empty scalar string fields leave the existing value untouched. A KEY policy stays on its client: a change to or from KEY scope, or to another key, returns INVALID_ARGUMENT. The owner of a key can update its KEY policy without project_id (fraser#10611). The policy id must be set inside the traffic_split_policy field.

Request fields:

FieldRequiredDescription
traffic_split_policyyesRequired: policy to update. traffic_split_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idnoProject that owns the target policy. A KEY policy may omit it; when set, the key must belong to this project.

Response fields:

FieldRequiredDescription
traffic_split_policynoThe updated policy with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) UpdateTrafficSplitPolicy(ctx context.Context, req *policyv1.UpdateTrafficSplitPolicyRequest) (*policyv1.UpdateTrafficSplitPolicyResponse, error)","python":"update_traffic_split_policy(req: policy_pb2.UpdateTrafficSplitPolicyRequest) -\u003e UpdateTrafficSplitPolicyResponse","typescript":"updateTrafficSplitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateTrafficSplitPolicyRequestSchema\u003e): Promise\u003cUpdateTrafficSplitPolicyResponse\u003e","cli":"tare api policy traffic-split-policies update --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"traffic_split_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateTrafficSplitPolicyRequest{}\n\n\tresp, err := client.Policy().UpdateTrafficSplitPolicy(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/policy/updatetrafficsplitpolicy\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.policy.v1 import policy_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 = policy_pb2.UpdateTrafficSplitPolicyRequest()\ntry:\n    result = client.policy.update_traffic_split_policy(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.policy.updateTrafficSplitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies update --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"traffic_split_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{traffic_split_policy.id}","slug":"update-a-traffic-split-policy"}

Delete a traffic split policy

What it does: Deletes a traffic split policy.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to delete.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idyesRequired: project that owns the target policy.
{"signatures":{"go":"func (x *PolicyClient) DeleteTrafficSplitPolicy(ctx context.Context, req *policyv1.DeleteTrafficSplitPolicyRequest) (*policyv1.DeleteTrafficSplitPolicyResponse, error)","python":"delete_traffic_split_policy(req: policy_pb2.DeleteTrafficSplitPolicyRequest) -\u003e DeleteTrafficSplitPolicyResponse","typescript":"deleteTrafficSplitPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteTrafficSplitPolicyRequestSchema\u003e): Promise\u003cDeleteTrafficSplitPolicyResponse\u003e","cli":"tare api policy traffic-split-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteTrafficSplitPolicyRequest{}\n\n\tresp, err := client.Policy().DeleteTrafficSplitPolicy(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/policy/deletetrafficsplitpolicy\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.policy.v1 import policy_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 = policy_pb2.DeleteTrafficSplitPolicyRequest()\ntry:\n    result = client.policy.delete_traffic_split_policy(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.policy.deleteTrafficSplitPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{id}","slug":"delete-a-traffic-split-policy"}

Set traffic split policy status

Changed in v0.10.0 (behaviour changes): Saving a project's fallback or traffic split policy, or turning one back on, is refused when one of its models, or that model's provider, is not available to the project, matching what the data plane serves. Before, traffic split checked neither and fallback did not check providers. A tag policy is also refused when it names a disabled model.

Changed in v0.9.0 (new features): The owner of an API key can set and turn off the fallback and traffic split policies of that key, without a project role.

Changed in v0.9.0 (new features): Traffic split policies can target one API key, and hold one weighted split for each primary model in the new entries field. Each entry needs a different primary model name. Create, update and status calls also work on a path without a project. A per-key split is refused when a model or its provider is not available to the key's project, except in the default project. A model can have weight 0 if another has more.

What it does: Toggles a traffic split policy's active/inactive state (is_active). The owner of a key can set the status of its KEY policy without project_id (fraser#10611).

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
statusyesRequired: new operational status for the policy.
customer_idyesRequired: customer (tenant) that owns the target policy.
project_idnoProject that owns the target policy. A KEY policy may omit it; when set, the key must belong to this project.

Response fields:

FieldRequiredDescription
traffic_split_policynoThe policy with the updated status.
{"signatures":{"go":"func (x *PolicyClient) SetTrafficSplitPolicyStatus(ctx context.Context, req *policyv1.SetTrafficSplitPolicyStatusRequest) (*policyv1.SetTrafficSplitPolicyStatusResponse, error)","python":"set_traffic_split_policy_status(req: policy_pb2.SetTrafficSplitPolicyStatusRequest) -\u003e SetTrafficSplitPolicyStatusResponse","typescript":"setTrafficSplitPolicyStatus(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetTrafficSplitPolicyStatusRequestSchema\u003e): Promise\u003cSetTrafficSplitPolicyStatusResponse\u003e","cli":"tare api policy traffic-split-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetTrafficSplitPolicyStatusRequest{}\n\n\tresp, err := client.Policy().SetTrafficSplitPolicyStatus(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/policy/settrafficsplitpolicystatus\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.policy.v1 import policy_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 = policy_pb2.SetTrafficSplitPolicyStatusRequest()\ntry:\n    result = client.policy.set_traffic_split_policy_status(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.policy.setTrafficSplitPolicyStatus(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy traffic-split-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{id}/status","slug":"set-traffic-split-policy-status"}

List unified policies

Changed in v0.5.0 (new features): The unified policy list now includes attribute-routing policies alongside the budget, rate-limit, fallback-chain and traffic-split rows, naming each policy's target, effective project, and monitor or enforce mode, and appearing only where the caller could read it directly. For these rows match_count counts the eligible keys for which the policy is the enabled winner; a paused policy reports zero.

What it does: Returns a read-only, paginated list for the caller's tenant. Budget, rate-limit, fallback-chain and traffic-split policies include only PROJECT and TAG targets. Their KEY targets remain on the key's config page; the other legacy budget/rate-limit scopes remain excluded. Attribute-routing policies include PROJECT and KEY targets. A row appears only when the caller could read it through GetAttributeRoutingPolicy in its effective project. Visibility and request filters apply before totals and pagination. Mutations still use each family's type-specific RPCs. UnifiedPolicy.match_count retains target membership counts for the existing families. Attribute-routing coverage counts eligible keys where the policy is the enabled winner, independent of monitor/enforce mode.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs.
customer_idnoOptional: customer (tenant) scope. Resolved the same way every other PolicyService read RPC resolves it (resolvePolicyCustomerID): defaults from the caller's authenticated claims when unset.
typesnoFilter to these policy types. Empty means all supported types.
statusesnoFilter to policies in these statuses. Empty means all statuses.

Response fields:

FieldRequiredDescription
policiesnoPolicies matching the request filters, one page's worth. Sorted by updated_at descending (most recently changed first).
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListPolicies(ctx context.Context, req *policyv1.ListPoliciesRequest) (*policyv1.ListPoliciesResponse, error)","python":"list_policies(req: policy_pb2.ListPoliciesRequest) -\u003e ListPoliciesResponse","typescript":"listPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListPoliciesRequestSchema\u003e): Promise\u003cListPoliciesResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListPoliciesRequest{}\n\n\tresp, err := client.Policy().ListPolicies(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/policy/listpolicies\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.policy.v1 import policy_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 = policy_pb2.ListPoliciesRequest()\ntry:\n    result = client.policy.list_policies(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.policy.listPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/policies","slug":"list-unified-policies"}

Create a request attribute

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Adds one entry to the customer's org-wide routing vocabulary.

Request fields:

FieldRequiredDescription
request_attributeyesRequired: vocabulary entry to create. id must be absent (server-assigned).
customer_idyesRequired: customer (tenant) that will own the entry. The vocabulary is org-wide, so this is the entry's real owning scope.
project_idyesRequired: project the caller is acting in. Read by the auth layer to authorize the caller; it does NOT scope the created entry, which is org-wide. See the file-level PROJECT SCOPING note.

Response fields:

FieldRequiredDescription
request_attributenoThe created entry with server-assigned fields populated.
{"signatures":{"go":"func (x *PolicyClient) CreateRequestAttribute(ctx context.Context, req *policyv1.CreateRequestAttributeRequest) (*policyv1.CreateRequestAttributeResponse, error)","python":"create_request_attribute(req: policy_pb2.CreateRequestAttributeRequest) -\u003e CreateRequestAttributeResponse","typescript":"createRequestAttribute(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateRequestAttributeRequestSchema\u003e): Promise\u003cCreateRequestAttributeResponse\u003e","cli":"tare api policy request-attributes create --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"request_attribute\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateRequestAttributeRequest{}\n\n\tresp, err := client.Policy().CreateRequestAttribute(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/policy/createrequestattribute\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.policy.v1 import policy_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 = policy_pb2.CreateRequestAttributeRequest()\ntry:\n    result = client.policy.create_request_attribute(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.policy.createRequestAttribute(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy request-attributes create --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"request_attribute\": {}\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes","slug":"create-a-request-attribute"}

Get a request attribute

Changed in v0.7.0 (security updates): Project-scoped attribute-routing reads now stay within the authorized project, so callers can no longer view another project's routing rules, condition values, or policy target identifiers such as target_api_key_id.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Returns a single vocabulary entry by id, including the policies that reference it so a caller can tell whether deleting it would break a live rule. A project-scoped read is confined to the project through which the caller was authorized; an org-wide read requires organization-level read access.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the entry to fetch.
customer_idnoOptional: customer (tenant) scope.
project_idnoOptional: project through which the caller is authorized. When omitted, an org-wide read requires organization-level read access; a project-scoped caller is confined to the project in its claims. Referencing policies and their count are limited to that authorized project.

Response fields:

FieldRequiredDescription
request_attributenoThe requested entry, with referencing_policy_count and the full referencing_policies list populated.
{"signatures":{"go":"func (x *PolicyClient) GetRequestAttribute(ctx context.Context, req *policyv1.GetRequestAttributeRequest) (*policyv1.GetRequestAttributeResponse, error)","python":"get_request_attribute(req: policy_pb2.GetRequestAttributeRequest) -\u003e GetRequestAttributeResponse","typescript":"getRequestAttribute(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetRequestAttributeRequestSchema\u003e): Promise\u003cGetRequestAttributeResponse\u003e","cli":"tare api policy request-attributes get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetRequestAttributeRequest{}\n\n\tresp, err := client.Policy().GetRequestAttribute(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/policy/getrequestattribute\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.policy.v1 import policy_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 = policy_pb2.GetRequestAttributeRequest()\ntry:\n    result = client.policy.get_request_attribute(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.policy.getRequestAttribute(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy request-attributes get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/request-attributes/{id}","slug":"get-a-request-attribute"}

List request attributes

Changed in v0.7.0 (security updates): Project-scoped attribute-routing reads now stay within the authorized project, so callers can no longer view another project's routing rules, condition values, or policy target identifiers such as target_api_key_id.

Changed in v0.5.0 (behaviour changes): ListRequestAttributes now accepts an optional search, returns unfiltered catalog stats, supports sorting by name, value_type or referencing_policy_count, and rejects unsupported page.filter or page.order_by values with InvalidArgument instead of ignoring them.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Returns the customer's routing vocabulary, ordered by name. A project-scoped read is confined to the project through which the caller was authorized; an org-wide read requires organization-level read access.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs. page.order_by accepts a single field, one of name, value_type or referencing_policy_count, optionally followed by asc or desc (AIP-132). Empty order_by means name asc. page.filter is not supported and is rejected rather than ignored. Page tokens are bound to the normalized order, search, customer scope and authorized project scope.
customer_idnoOptional: customer (tenant) scope.
project_idnoOptional: project through which the caller is authorized. When omitted, an org-wide read requires organization-level read access; a project-scoped caller is confined to the project in its claims. Referencing-policy counts and page ordering are limited to that authorized project.
searchnoOptional case-insensitive substring search on the attribute name or any allowed value. Surrounding whitespace is ignored. Applies before sorting and pagination, and response.total counts the matching entries.

Response fields:

FieldRequiredDescription
request_attributesnoThe matching vocabulary, one page's worth in the requested order.
pagenoCursor-pagination outputs.
totalnoTotal count of matching entries across all pages.
statsnoUnfiltered catalog totals for the overview cards. These counts ignore search and pagination and are computed over the same customer scope.
{"signatures":{"go":"func (x *PolicyClient) ListRequestAttributes(ctx context.Context, req *policyv1.ListRequestAttributesRequest) (*policyv1.ListRequestAttributesResponse, error)","python":"list_request_attributes(req: policy_pb2.ListRequestAttributesRequest) -\u003e ListRequestAttributesResponse","typescript":"listRequestAttributes(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListRequestAttributesRequestSchema\u003e): Promise\u003cListRequestAttributesResponse\u003e","cli":"tare api policy request-attributes list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListRequestAttributesRequest{}\n\n\tresp, err := client.Policy().ListRequestAttributes(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/policy/listrequestattributes\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.policy.v1 import policy_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 = policy_pb2.ListRequestAttributesRequest()\ntry:\n    result = client.policy.list_request_attributes(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.policy.listRequestAttributes(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy request-attributes list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/request-attributes","slug":"list-request-attributes"}

Update a request attribute

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Replaces a vocabulary entry's name, value type and allowed values. Removing an allowed value that a live rule compares against is permitted and does NOT break the rule structurally; it makes that condition stop matching, which is why fraser#8662 warns first.

Request fields:

FieldRequiredDescription
request_attributeyesRequired: entry to update. request_attribute.id must be set. name, value_type and allowed_values are replaced wholesale.
customer_idyesRequired: customer (tenant) that owns the entry.
project_idyesRequired: project the caller is acting in. Authorization only.

Response fields:

FieldRequiredDescription
request_attributenoThe updated entry.
{"signatures":{"go":"func (x *PolicyClient) UpdateRequestAttribute(ctx context.Context, req *policyv1.UpdateRequestAttributeRequest) (*policyv1.UpdateRequestAttributeResponse, error)","python":"update_request_attribute(req: policy_pb2.UpdateRequestAttributeRequest) -\u003e UpdateRequestAttributeResponse","typescript":"updateRequestAttribute(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateRequestAttributeRequestSchema\u003e): Promise\u003cUpdateRequestAttributeResponse\u003e","cli":"tare api policy request-attributes update --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"request_attribute\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateRequestAttributeRequest{}\n\n\tresp, err := client.Policy().UpdateRequestAttribute(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/policy/updaterequestattribute\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.policy.v1 import policy_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 = policy_pb2.UpdateRequestAttributeRequest()\ntry:\n    result = client.policy.update_request_attribute(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.policy.updateRequestAttribute(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy request-attributes update --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"request_attribute\": {}\n  }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes/{request_attribute.id}","slug":"update-a-request-attribute"}

Delete a request attribute

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Removes a vocabulary entry. Refused with FailedPrecondition, naming the blocking policies, when a live rule condition still compares against it.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the entry to delete.
customer_idyesRequired: customer (tenant) that owns the entry.
project_idyesRequired: project the caller is acting in. Authorization only.
{"signatures":{"go":"func (x *PolicyClient) DeleteRequestAttribute(ctx context.Context, req *policyv1.DeleteRequestAttributeRequest) (*policyv1.DeleteRequestAttributeResponse, error)","python":"delete_request_attribute(req: policy_pb2.DeleteRequestAttributeRequest) -\u003e DeleteRequestAttributeResponse","typescript":"deleteRequestAttribute(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteRequestAttributeRequestSchema\u003e): Promise\u003cDeleteRequestAttributeResponse\u003e","cli":"tare api policy request-attributes delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteRequestAttributeRequest{}\n\n\tresp, err := client.Policy().DeleteRequestAttribute(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/policy/deleterequestattribute\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.policy.v1 import policy_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 = policy_pb2.DeleteRequestAttributeRequest()\ntry:\n    result = client.policy.delete_request_attribute(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.policy.deleteRequestAttribute(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy request-attributes delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes/{id}","slug":"delete-a-request-attribute"}

Create an attribute routing policy

Changed in v0.6.0 (new features): Attribute-routing policies now report rule_count and distinct_destination_model_count on every read, including the list, so a list can show how many rules a policy has and how many models they route to without loading the rules.

Changed in v0.6.0 (bug fixes): Project-scoped traffic-split, fallback-chain and attribute routing policies now create and update successfully when no tag selector is supplied.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Creates an ordered rule list bound to a project or a key. The created policy is always in MONITOR mode: nothing moves traffic until SetAttributeRoutingPolicyMode flips it. KNOWN LIMITATION. A destination is checked against the target project's catalog at save time, which is early feedback rather than a guarantee. Availability for a given key also depends on the provider, the project's provider filter, the key's own route map and the gateway binding, all of which are resolved when the routing snapshot is rendered. A rule can therefore save cleanly and still never fire, because the destination was dropped at render time.

Request fields:

FieldRequiredDescription
attribute_routing_policyyesRequired: policy to create. id must be absent (server-assigned), and mode is ignored -- a created policy is always in MONITOR.
customer_idyesRequired: customer (tenant) that will own the policy.
project_idyesRequired: project that will own the policy.

Response fields:

FieldRequiredDescription
attribute_routing_policynoThe created policy, in MONITOR mode, with server-assigned rule ids.
{"signatures":{"go":"func (x *PolicyClient) CreateAttributeRoutingPolicy(ctx context.Context, req *policyv1.CreateAttributeRoutingPolicyRequest) (*policyv1.CreateAttributeRoutingPolicyResponse, error)","python":"create_attribute_routing_policy(req: policy_pb2.CreateAttributeRoutingPolicyRequest) -\u003e CreateAttributeRoutingPolicyResponse","typescript":"createAttributeRoutingPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.CreateAttributeRoutingPolicyRequestSchema\u003e): Promise\u003cCreateAttributeRoutingPolicyResponse\u003e","cli":"tare api policy attribute-routing-policies create --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"attribute_routing_policy\": {}\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.CreateAttributeRoutingPolicyRequest{}\n\n\tresp, err := client.Policy().CreateAttributeRoutingPolicy(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/policy/createattributeroutingpolicy\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.policy.v1 import policy_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 = policy_pb2.CreateAttributeRoutingPolicyRequest()\ntry:\n    result = client.policy.create_attribute_routing_policy(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.policy.createAttributeRoutingPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies create --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"attribute_routing_policy\": {}\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies","slug":"create-an-attribute-routing-policy"}

Get an attribute routing policy

Changed in v0.7.0 (security updates): Project-scoped attribute-routing reads now stay within the authorized project, so callers can no longer view another project's routing rules, condition values, or policy target identifiers such as target_api_key_id.

Changed in v0.6.0 (new features): Attribute-routing policies now report rule_count and distinct_destination_model_count on every read, including the list, so a list can show how many rules a policy has and how many models they route to without loading the rules.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Returns a single policy with its ordered rules and their conditions.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to fetch.
customer_idnoOptional: customer (tenant) scope.
project_idyesRequired: project against which the policy is authorized.

Response fields:

FieldRequiredDescription
attribute_routing_policynoThe requested policy with its ordered rules and conditions.
{"signatures":{"go":"func (x *PolicyClient) GetAttributeRoutingPolicy(ctx context.Context, req *policyv1.GetAttributeRoutingPolicyRequest) (*policyv1.GetAttributeRoutingPolicyResponse, error)","python":"get_attribute_routing_policy(req: policy_pb2.GetAttributeRoutingPolicyRequest) -\u003e GetAttributeRoutingPolicyResponse","typescript":"getAttributeRoutingPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetAttributeRoutingPolicyRequestSchema\u003e): Promise\u003cGetAttributeRoutingPolicyResponse\u003e","cli":"tare api policy attribute-routing-policies get \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H...?project_id=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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetAttributeRoutingPolicyRequest{}\n\n\tresp, err := client.Policy().GetAttributeRoutingPolicy(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/policy/getattributeroutingpolicy\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.policy.v1 import policy_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 = policy_pb2.GetAttributeRoutingPolicyRequest()\ntry:\n    result = client.policy.get_attribute_routing_policy(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.policy.getAttributeRoutingPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies get \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H...?project_id=proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/attribute-routing-policies/{id}","slug":"get-an-attribute-routing-policy"}

Get attribute routing policy analytics

Changed in v0.6.0 (new features): Attribute-routing policies now report their routing decisions over a selected lookback period. The readout breaks requests down by the rule or default that matched, the destination provider and model, and monitor or enforce mode, counts requests that carried an attribute value outside its allowed set, and states the time through which routing data is available. Use it to review a policy in monitor mode before enforcing it. Reading it requires attribute_routing_policies.read on the project.

What it does: Returns the monitor/enforce readout derived from hourly routing-decision rollups.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy whose routing decisions are read.
customer_idnoOptional: customer (tenant) scope. When omitted it is resolved from the authenticated caller; an explicit mismatch is rejected.
project_idyesRequired: project against which the policy is authorized.
lookback_daysnoOptional: the window is exactly N days of completed UTC hours, ending at the start of the current hour. The hour in progress is not included. 0 selects the server default of 7.
pagenoOptional pagination and ordering for decision readout entries. The default order follows policy evaluation order. Supported order_by fields are rule_order, request_count, out_of_set_count, destination_provider, destination_model, and mode. filter is not supported.

Response fields:

FieldRequiredDescription
analyticsnoSummary for the complete requested window, independent of pagination.
entriesnoOne page of matched-rule and default-outcome decision buckets.
pagenoCursor for the next page. Empty when the listing is exhausted.
totalnoNumber of decision entries in the complete requested window.
{"signatures":{"go":"func (x *PolicyClient) GetAttributeRoutingPolicyAnalytics(ctx context.Context, req *policyv1.GetAttributeRoutingPolicyAnalyticsRequest) (*policyv1.GetAttributeRoutingPolicyAnalyticsResponse, error)","python":"get_attribute_routing_policy_analytics(req: policy_pb2.GetAttributeRoutingPolicyAnalyticsRequest) -\u003e GetAttributeRoutingPolicyAnalyticsResponse","typescript":"getAttributeRoutingPolicyAnalytics(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.GetAttributeRoutingPolicyAnalyticsRequestSchema\u003e): Promise\u003cGetAttributeRoutingPolicyAnalyticsResponse\u003e","cli":"tare api policy attribute-routing-policies analytics \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H.../analytics?project_id=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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.GetAttributeRoutingPolicyAnalyticsRequest{}\n\n\tresp, err := client.Policy().GetAttributeRoutingPolicyAnalytics(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/policy/getattributeroutingpolicyanalytics\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.policy.v1 import policy_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 = policy_pb2.GetAttributeRoutingPolicyAnalyticsRequest()\ntry:\n    result = client.policy.get_attribute_routing_policy_analytics(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.policy.getAttributeRoutingPolicyAnalytics(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies analytics \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H.../analytics?project_id=proj_01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/attribute-routing-policies/{id}/analytics","slug":"get-attribute-routing-policy-analytics"}

List attribute routing policies

Changed in v0.7.0 (security updates): Project-scoped attribute-routing reads now stay within the authorized project, so callers can no longer view another project's routing rules, condition values, or policy target identifiers such as target_api_key_id.

Changed in v0.7.0 (bug fixes): Listing attribute routing policies now rejects a scope_types or statuses filter it cannot apply, instead of ignoring it and returning a broader list than requested. Only KEY and PROJECT scopes are accepted.

Changed in v0.6.0 (behaviour changes): Listing attribute-routing policies for a project now requires the user's own attribute_routing_policies.read grant on that project.

Changed in v0.6.0 (new features): Attribute-routing policies can now be listed across the whole organization by leaving out project_id, with each policy naming the project it applies to. This needs organization-level read access.

Changed in v0.6.0 (new features): Attribute-routing policies now report rule_count and distinct_destination_model_count on every read, including the list, so a list can show how many rules a policy has and how many models they route to without loading the rules.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Returns policies matching the filters, WITHOUT their rule bodies: the list surfaces show targets, modes, and a lightweight rule_count / distinct_destination_model_count summary. Use GetAttributeRoutingPolicy to load the rules themselves.

Request fields:

FieldRequiredDescription
pagenoCursor-pagination inputs. page.order_by accepts a single field, one of created_at, updated_at, scope_type, mode, status or default_model, optionally followed by asc or desc (AIP-132). Empty order_by means created_at desc. scope_type and mode sort in their enum declaration order (key before project, monitor before enforce), and status asc lists active policies before inactive ones. Ties break on the policy id. page.filter is not supported and is rejected rather than ignored. Page tokens are bound to the normalized order, filters, project and customer scope; reusing one with any of them changed is INVALID_ARGUMENT, so restart from the first page instead.
scope_typesnoFilter to policies with these scope types. Only KEY and PROJECT are supported; UNSPECIFIED, ORGANIZATION and TAG are rejected with INVALID_ARGUMENT. Naming both KEY and PROJECT (including duplicate values of either) is the unfiltered read because the repository cannot express a multi-scope filter.
statusesnoFilter to policies in these statuses. Only ACTIVE and INACTIVE are supported; UNSPECIFIED is rejected with INVALID_ARGUMENT. Naming both statuses is the unfiltered read.
target_project_idnoFilter to policies targeting this target_project_id (project slug).
customer_idnoOptional: customer (tenant) scope.
project_idnoOptional: project boundary for the list. When set, results are restricted to policies effective for this project. When omitted, the list spans every project in the customer and is authorized at org scope, so only a caller with an org-level read grant can make it. Each row's effective_project_id names the project it applies to either way.

Response fields:

FieldRequiredDescription
attribute_routing_policiesnoPolicies matching the filters, WITHOUT their rule bodies.
pagenoCursor-pagination outputs.
totalnoTotal count of matching policies across all pages.
{"signatures":{"go":"func (x *PolicyClient) ListAttributeRoutingPolicies(ctx context.Context, req *policyv1.ListAttributeRoutingPoliciesRequest) (*policyv1.ListAttributeRoutingPoliciesResponse, error)","python":"list_attribute_routing_policies(req: policy_pb2.ListAttributeRoutingPoliciesRequest) -\u003e ListAttributeRoutingPoliciesResponse","typescript":"listAttributeRoutingPolicies(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.ListAttributeRoutingPoliciesRequestSchema\u003e): Promise\u003cListAttributeRoutingPoliciesResponse\u003e","cli":"tare api policy attribute-routing-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies\" \\\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.ListAttributeRoutingPoliciesRequest{}\n\n\tresp, err := client.Policy().ListAttributeRoutingPolicies(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/policy/listattributeroutingpolicies\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.policy.v1 import policy_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 = policy_pb2.ListAttributeRoutingPoliciesRequest()\ntry:\n    result = client.policy.list_attribute_routing_policies(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.policy.listAttributeRoutingPolicies(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/attribute-routing-policies","slug":"list-attribute-routing-policies"}

Update an attribute routing policy

Changed in v0.6.0 (new features): Attribute-routing policies now report rule_count and distinct_destination_model_count on every read, including the list, so a list can show how many rules a policy has and how many models they route to without loading the rules.

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Applies a partial update. A present rules field replaces the ENTIRE rule list: a rule carrying its id is updated in place, a rule with no id is created, and a rule left out is deleted. Omitting rules leaves the list untouched. Mode, status, scope_type, target_api_key_id, and target_project_id are NOT settable here. KNOWN LIMITATION. A destination is checked against the target project's catalog at save time, which is early feedback rather than a guarantee. Availability for a given key also depends on the provider, the project's provider filter, the key's own route map and the gateway binding, all of which are resolved when the routing snapshot is rendered. A rule can therefore save cleanly and still never fire, because the destination was dropped at render time.

Request fields:

FieldRequiredDescription
attribute_routing_policyyesRequired: policy to update. attribute_routing_policy.id must be set. Partial update: an omitted/empty scalar leaves the stored value untouched. Mode and status are NOT settable here; use SetAttributeRoutingPolicyMode and SetAttributeRoutingPolicyStatus. scope_type, target_api_key_id, and target_project_id are immutable; create a new policy to change its target.
customer_idyesRequired: customer (tenant) that owns the policy.
project_idyesRequired: project that owns the policy.
clear_rulesnoDelete every rule, leaving a policy that always takes its default. proto3 cannot tell an omitted repeated field from an empty one, and both are meaningful here, so emptying the list needs its own signal. A non-empty attribute_routing_policy.rules replaces the whole list regardless of this flag; an empty rules with clear_rules = false (the default) leaves the stored rules untouched. Mirrors clear_tags / clear_scopes on UpdateApiKeyRequest.

Response fields:

FieldRequiredDescription
attribute_routing_policynoThe updated policy with its resulting rule list.
{"signatures":{"go":"func (x *PolicyClient) UpdateAttributeRoutingPolicy(ctx context.Context, req *policyv1.UpdateAttributeRoutingPolicyRequest) (*policyv1.UpdateAttributeRoutingPolicyResponse, error)","python":"update_attribute_routing_policy(req: policy_pb2.UpdateAttributeRoutingPolicyRequest) -\u003e UpdateAttributeRoutingPolicyResponse","typescript":"updateAttributeRoutingPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.UpdateAttributeRoutingPolicyRequestSchema\u003e): Promise\u003cUpdateAttributeRoutingPolicyResponse\u003e","cli":"tare api policy attribute-routing-policies update --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"attribute_routing_policy\": {},\n    \"clear_rules\": 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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.UpdateAttributeRoutingPolicyRequest{}\n\n\tresp, err := client.Policy().UpdateAttributeRoutingPolicy(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/policy/updateattributeroutingpolicy\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.policy.v1 import policy_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 = policy_pb2.UpdateAttributeRoutingPolicyRequest()\ntry:\n    result = client.policy.update_attribute_routing_policy(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.policy.updateAttributeRoutingPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies update --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"attribute_routing_policy\": {},\n    \"clear_rules\": false\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{attribute_routing_policy.id}","slug":"update-an-attribute-routing-policy"}

Delete an attribute routing policy

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Removes a policy; its rules and conditions go with it.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to delete.
customer_idyesRequired: customer (tenant) that owns the policy.
project_idyesRequired: project that owns the policy.
{"signatures":{"go":"func (x *PolicyClient) DeleteAttributeRoutingPolicy(ctx context.Context, req *policyv1.DeleteAttributeRoutingPolicyRequest) (*policyv1.DeleteAttributeRoutingPolicyResponse, error)","python":"delete_attribute_routing_policy(req: policy_pb2.DeleteAttributeRoutingPolicyRequest) -\u003e DeleteAttributeRoutingPolicyResponse","typescript":"deleteAttributeRoutingPolicy(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.DeleteAttributeRoutingPolicyRequestSchema\u003e): Promise\u003cDeleteAttributeRoutingPolicyResponse\u003e","cli":"tare api policy attribute-routing-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.DeleteAttributeRoutingPolicyRequest{}\n\n\tresp, err := client.Policy().DeleteAttributeRoutingPolicy(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/policy/deleteattributeroutingpolicy\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.policy.v1 import policy_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 = policy_pb2.DeleteAttributeRoutingPolicyRequest()\ntry:\n    result = client.policy.delete_attribute_routing_policy(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.policy.deleteAttributeRoutingPolicy(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}","slug":"delete-an-attribute-routing-policy"}

Set attribute routing policy status

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Switches a policy on or off. Independent of mode: pausing a policy does not forget whether it monitors or enforces.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
statusyesRequired: new operational status.
customer_idyesRequired: customer (tenant) that owns the policy.
project_idyesRequired: project that owns the policy.

Response fields:

FieldRequiredDescription
attribute_routing_policynoThe policy with the updated status.
{"signatures":{"go":"func (x *PolicyClient) SetAttributeRoutingPolicyStatus(ctx context.Context, req *policyv1.SetAttributeRoutingPolicyStatusRequest) (*policyv1.SetAttributeRoutingPolicyStatusResponse, error)","python":"set_attribute_routing_policy_status(req: policy_pb2.SetAttributeRoutingPolicyStatusRequest) -\u003e SetAttributeRoutingPolicyStatusResponse","typescript":"setAttributeRoutingPolicyStatus(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetAttributeRoutingPolicyStatusRequestSchema\u003e): Promise\u003cSetAttributeRoutingPolicyStatusResponse\u003e","cli":"tare api policy attribute-routing-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetAttributeRoutingPolicyStatusRequest{}\n\n\tresp, err := client.Policy().SetAttributeRoutingPolicyStatus(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/policy/setattributeroutingpolicystatus\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.policy.v1 import policy_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 = policy_pb2.SetAttributeRoutingPolicyStatusRequest()\ntry:\n    result = client.policy.set_attribute_routing_policy_status(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.policy.setAttributeRoutingPolicyStatus(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../status\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"status\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}/status","slug":"set-attribute-routing-policy-status"}

Set attribute routing policy mode

Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.

What it does: Flips a policy between monitoring and enforcing. Its own RPC, and its own audit action, because this is the moment live traffic starts moving.

Request fields:

FieldRequiredDescription
idyesRequired: uuid of the policy to update.
modeyesRequired: new mode. Flipping to ENFORCE is the moment live traffic starts moving, which is why it is this RPC rather than part of Update.
customer_idyesRequired: customer (tenant) that owns the policy.
project_idyesRequired: project that owns the policy.

Response fields:

FieldRequiredDescription
attribute_routing_policynoThe policy with the updated mode.
{"signatures":{"go":"func (x *PolicyClient) SetAttributeRoutingPolicyMode(ctx context.Context, req *policyv1.SetAttributeRoutingPolicyModeRequest) (*policyv1.SetAttributeRoutingPolicyModeResponse, error)","python":"set_attribute_routing_policy_mode(req: policy_pb2.SetAttributeRoutingPolicyModeRequest) -\u003e SetAttributeRoutingPolicyModeResponse","typescript":"setAttributeRoutingPolicyMode(req: MessageInitShape\u003ctypeof tars_policy_v1_policy_pb.SetAttributeRoutingPolicyModeRequestSchema\u003e): Promise\u003cSetAttributeRoutingPolicyModeResponse\u003e","cli":"tare api policy attribute-routing-policies set-mode --id $ID --mode $MODE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../mode\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"mode\": \"...\"\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\tpolicyv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/policy/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 := \u0026policyv1.SetAttributeRoutingPolicyModeRequest{}\n\n\tresp, err := client.Policy().SetAttributeRoutingPolicyMode(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/policy/setattributeroutingpolicymode\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.policy.v1 import policy_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 = policy_pb2.SetAttributeRoutingPolicyModeRequest()\ntry:\n    result = client.policy.set_attribute_routing_policy_mode(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.policy.setAttributeRoutingPolicyMode(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"policy\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"cli":"tare api policy attribute-routing-policies set-mode --id $ID --mode $MODE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../mode\" \\\n  -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"mode\": \"...\"\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}/mode","slug":"set-attribute-routing-policy-mode"}