Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

Docs: organizations' agent API in the reference; agent policy and status page on the docs home (#170)

The six /orgs/{org}/diffinery endpoints from #160 (agent policy, model
keys, model usage) get summaries, fields and owner-only access in the
generated API reference, with the scopes and sign-in they need. Get an
agent task names paid_by. The docs home links Agents in organizations
and the status page (#166).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016q5wwBFck8JHq14gHUM2CL
Canberk Demirci authored · GitHub committed signed1 parent c67c4e3commit ce129932f2a991d92589608700da868d64d0cfc6Browse files
2 files changed+52−1
modifiedapps/diffinery/docs/index.md+2−0View file
@@ -16,6 +16,7 @@
1616 | Connect an AI agent | [Agents](/docs/agents/overview) and [MCP](/docs/agents/mcp) |
1717 | Give an agent a goal and get a pull request back, with your own model key | [Agent tasks](/docs/agents/tasks) |
1818 | See the tokens and cost your agent tasks and reviews used | [Usage and cost](/docs/agents/tasks#usage-and-cost) |
19+| Pay for an organization's agents with its own keys, and set what they may use | [Agents in organizations](/docs/agents/organizations) |
1920 | Work in a browser shell with Claude Code or Codex on your own Claude or ChatGPT subscription, and give it tasks | [Terminals](/docs/agents/terminal) |
2021 | Track agent work on a board, with shared memory and project instructions | [Projects](/docs/agents/projects) |
2122 | See what needs you and what your agents did since yesterday | [Today](/docs/agents/today) |
@@ -23,6 +24,7 @@
2324 | Script against Diffinery | [REST API guide](/docs/reference/rest-api), [REST API reference](/docs/api) and [CLI reference](/docs/reference/cli) |
2425 | Export your data or delete your account | [Exporting and deleting your account](/docs/accounts/account-data) |
2526 | Run your own instance | [Deploy Diffinery](/docs/self-hosting/deploy) |
27+| Check whether Diffinery is up, or post an incident | [Status page](/docs/self-hosting/status-page) |
2628 | Report a security problem privately (the [report form](/security/report)) | [Reporting a vulnerability](/docs/security/disclosure) |
2729
2830 ## What you get
modifiedapps/diffinery/src/docs/api-meta.ts+50−1View file
@@ -78,6 +78,12 @@
7878 "DELETE /diffinery/model-keys/{provider}": { scope: "admin", sessionOnly: true },
7979 "GET /diffinery/model-keys": { scope: "read", anyToken: true },
8080 "GET /diffinery/model-usage": { scope: "read", anyToken: true },
81+ "GET /orgs/{org}/diffinery/agent-policy": { scope: "read" },
82+ "PUT /orgs/{org}/diffinery/agent-policy": { scope: "admin", sessionOnly: true },
83+ "GET /orgs/{org}/diffinery/model-keys": { scope: "read" },
84+ "PUT /orgs/{org}/diffinery/model-keys/{provider}": { scope: "admin", sessionOnly: true },
85+ "DELETE /orgs/{org}/diffinery/model-keys/{provider}": { scope: "admin", sessionOnly: true },
86+ "GET /orgs/{org}/diffinery/model-usage": { scope: "read" },
8187 "GET /diffinery/tasks": { scope: "read", anyToken: true },
8288 "POST /repos/{owner}/{repo}/diffinery/tasks": { scope: "write", sessionOnly: true },
8389 "POST /repos/{owner}/{repo}/diffinery/tasks/{number}/messages": { scope: "write", sessionOnly: true },
@@ -1682,6 +1688,49 @@
16821688 access: "account",
16831689 query: { days: ["integer", "1 to 90 (default 30)."] },
16841690 },
1691+ "GET /orgs/{org}/diffinery/agent-policy": {
1692+ summary: "Get an organization's agent policy",
1693+ description: "Owners only (and site administrators); a token limited to repositories gets 403. `keys` (`personal`, `either` or `organization`: whose key pays), `runtimes` (`claude-code`, `codex`, `custom`), `providers` (`anthropic`, `openai`, `openrouter`), `max_running` (tasks at once per repository, 1 to 10), `terminals`, `terminal_tasks`, `review`, `member_monthly_tokens` (`null` for no allowance), `updated_by` and `updated_at`. See /docs/agents/organizations.",
1694+ access: "org-owner",
1695+ },
1696+ "PUT /orgs/{org}/diffinery/agent-policy": {
1697+ summary: "Change an organization's agent policy",
1698+ description: "From a browser session only, by an owner. Fields left out stay as they are; answers with the whole policy. 422 when a value is out of range, or no runtime or provider is left allowed. Each repository's tasks at once are held to `max_running` right away. Audited as `org.agent_policy.update`, with the new values.",
1699+ access: "org-owner",
1700+ body: {
1701+ keys: ["string", "`personal` (each person's own keys), `either` (the organization's keys when it has them) or `organization` (only the organization's keys)."],
1702+ runtimes: ["array", "Allowed runtimes: `claude-code`, `codex`, `custom`. At least one."],
1703+ providers: ["array", "Allowed providers: `anthropic`, `openai`, `openrouter`. At least one."],
1704+ max_running: ["integer", "Most tasks at once per repository, 1 to 10."],
1705+ terminals: ["boolean", "Allow web terminals."],
1706+ terminal_tasks: ["boolean", "Let terminals run agent tasks."],
1707+ review: ["boolean", "Allow agent review."],
1708+ member_monthly_tokens: ["integer", "Tokens one person may spend of the organization's keys in a calendar month (UTC), 10,000 to 10,000,000,000, or `null` for no allowance."],
1709+ },
1710+ },
1711+ "GET /orgs/{org}/diffinery/model-keys": {
1712+ summary: "List an organization's model keys",
1713+ description: "Owners only; a token limited to repositories gets 403. Each key as `GET /diffinery/model-keys` shows a personal one: `provider`, `hint` (last four characters), `opted_in_at`, `created_at` and `updated_at`. The keys themselves are never returned. See /docs/agents/organizations.",
1714+ access: "org-owner",
1715+ },
1716+ "PUT /orgs/{org}/diffinery/model-keys/{provider}": {
1717+ summary: "Save an organization's model key",
1718+ description: "From a browser session with a sign-in from the last 2 hours, by an owner. `provider` is `anthropic`, `openai` or `openrouter`; `accept_terms: true` is required. The key is encrypted, never shown again and never sent to a sandbox. Every owner gets a security email. Audited as `org.model_key.set`.",
1719+ access: "org-owner",
1720+ body: { key: ["string", "The API key (`sk-ant-...`, `sk-...` or `sk-or-...`)."], accept_terms: ["boolean", "Must be `true`."] },
1721+ },
1722+ "DELETE /orgs/{org}/diffinery/model-keys/{provider}": {
1723+ summary: "Delete an organization's model key",
1724+ description: "From a browser session with a sign-in from the last 2 hours, by an owner. 404 when the organization has no key for that provider. Audited as `org.model_key.delete`.",
1725+ access: "org-owner",
1726+ status: 204,
1727+ },
1728+ "GET /orgs/{org}/diffinery/model-usage": {
1729+ summary: "Get an organization's model usage",
1730+ description: "Owners only; a token limited to repositories gets 403. The runs the organization's keys paid for over the last `days`, shaped like `GET /diffinery/model-usage` with a `person` on each line, and `month`: `month`, `member_monthly_tokens` and `people` (each `person` and their `tokens` on the organization's keys this month). See /docs/agents/organizations#usage.",
1731+ access: "org-owner",
1732+ query: { days: ["integer", "1 to 90 (default 30)."] },
1733+ },
16851734 "PUT /diffinery/model-keys/{provider}": {
16861735 summary: "Save a model key",
16871736 description: "From a browser session only: no token, agent, job or sandbox can set a model key. `provider` is `anthropic`, `openai` or `openrouter`. `accept_terms: true` records that you use that provider through Diffinery under your own account and its terms (422 without it). The key is encrypted, never shown again and never sent to a sandbox. Sends you a security email. Audited as `model_key.set`.",
@@ -1786,7 +1835,7 @@
17861835 },
17871836 "GET /repos/{owner}/{repo}/diffinery/tasks/{number}": {
17881837 summary: "Get an agent task",
1789- description: "The task, its runs and its pull request. Needs write access. A plan-first task also has `plan_state` (`planning`, `waiting`, `approved` or `split`) and `plan`; a task split from a plan has `parent_task`. A task with more than one attempt has `pick_state` (`running`, `waiting` or `picked`) and `picked_attempt`, and each run its `attempt`. Every task has `fix_checks`, `check_fixes` (fix runs started so far) and `land`, and `usage` (the model usage of all its runs; each run has its own `usage`, with `source`: `proxy`, or `runtime` for a run in a terminal). See /docs/agents/tasks#usage-and-cost.",
1838+ description: "The task, its runs and its pull request. Needs write access. A plan-first task also has `plan_state` (`planning`, `waiting`, `approved` or `split`) and `plan`; a task split from a plan has `parent_task`. A task with more than one attempt has `pick_state` (`running`, `waiting` or `picked`) and `picked_attempt`, and each run its `attempt`. Every task has `fix_checks`, `check_fixes` (fix runs started so far) and `land`, `paid_by` (`person`, or `organization` when an organization's key pays), and `usage` (the model usage of all its runs; each run has its own `usage`, with `source`: `proxy`, or `runtime` for a run in a terminal). See /docs/agents/tasks#usage-and-cost.",
17901839 access: "write",
17911840 },
17921841 "PATCH /repos/{owner}/{repo}/diffinery/tasks/{number}": {