Skip to content
Last updated

Forge cloud compute

Forge cloud compute gives Forge a server to run agents and tests on while the Forge window stays on the person's Mac. The API under https://api.aitronos.com/v1/forge/compute lists where a server can run and at what price, connects an organization's own cloud accounts, and creates, parks, resumes, deletes and revokes servers. Everything that has to happen on the Mac — the SSH client key, installing Forge's runtime on the server, pairing and the tunnel — is done by the client; this API records each step.

Every endpoint is plain JSON request and response. Progress is polled, never streamed.

Access

  • Every endpoint requires the use_forge capability in the acting organization, except the three spend-limit endpoints for people who manage billing (below).
  • Connecting or disconnecting a cloud account, changing the organization's compute settings, deleting a leftover resource, listing every member's servers (?scope=org) and acting on a server someone else created require manage_forge (which includes use_forge).
  • Changing the organization's spend limits for Aitronos servers, listing every member's limits and setting one member's limit require manage_billing (the capability every spending limit is changed with) instead of use_forge. Reading the limits and setting your own needs only use_forge; your own limit needs a signed-in person.
  • A server is visible to the person who created it and to members with manage_forge. Anyone else is told it does not exist (404 FORGE_COMPUTE_HOST_NOT_FOUND).
  • Forge cloud compute is switched on per organization. While it is off, the catalog lists no offerings, and options, connecting an account, creating, resuming and the setup reports (progress, host key, ready, activity) are refused with 403 FORGE_COMPUTE_DISABLED. Reads, park, delete, revoke, disconnecting an account and deleting a leftover resource keep working, so switching the feature off never strands a server that costs money.

Which organization pays

Forge is not tied to one organization; a person may rent servers in any organization they belong to.

  • Choosing. List billing organizations lists every organization the person is an active member of, which ones servers can be billed to (selectable, with a reason to show when not) and which one to preselect (default_organization_id). Choose the default billing organization saves the preselection. Show the choice as Bill to on every rental.
  • Creating. Create a server names the organization in organization_id. The server is billed to that organization alone, for its whole life: every hour, every resume and its parked copy. The backend never infers it.
  • Finding a server again. Every server carries organization ({id, name}). List your servers in every organization lists the person's own servers across all of their organizations.
  • Acting on a server. Every other endpoint acts in the caller's current organization unless the request names another one with the organization_id query parameter or the X-Organization-Id header. Send the server's organization.id with every request about it. Naming an organization you are not an active member of is refused with 403 ORGANIZATION_ACCESS_DENIED; capabilities are checked in the named organization.

Project groups

A project group is a folder of projects in the Forge sidebar, and it can carry the organization that pays for the Forge spend made inside its projects: rented servers and the git impact assessment. Forge registers each group, keyed by its own id, with Register or update a project group, lists them with List project groups and removes one with Delete a project group; the API is under https://api.aitronos.com/v1/forge/project-groups. A group bills to its own organization, else to its nearest registered ancestor's (inherited), else to none; register every group, also those without an organization, so the groups inside them can inherit through them. A server rented inside a group sends project_group_id and must be created in the group's organization (422 FORGE_PROJECT_GROUP_ORGANIZATION_MISMATCH otherwise); it carries the group in project_group and stays billed to the organization it was rented in. Spend inside a group whose organization can no longer be billed is refused with 403 FORGE_PROJECT_GROUP_ORGANIZATION_UNAVAILABLE, never billed somewhere else. The organization's usage report shows its Forge spend per group in by_forge_project_group.

Two kinds of server

OfferingkindWho runs and bills it
aitronos — Aitronos serversmanagedAitronos runs the server and charges your organization per started hour, in CHF, as Forge cloud compute on its usage.
hetzner, digitalocean, vultr, scaleway, exoscale, linode, upcloudbyoThe server runs in your organization's own account at that provider. The provider bills your organization directly; Aitronos meters nothing.

Labels, order, help text and the connect form of each offering come from List compute offerings; a client should render what it receives rather than hard-code it.

Billing of Aitronos servers

  • Per started hour. Every started hour a server exists is charged once, from the moment the server is confirmed to exist until it is confirmed gone. An hour a server is parked and resumed in is charged once.
  • At the quoted price. The hourly price the person confirmed when creating (or resuming) the server is frozen on the server as price and is exactly what is charged. Each charge is recorded in CHF, already priced, in the organization's usage under Forge cloud compute; it is not converted from synapses or neurons.
  • CHF, excluding VAT. Prices already include your organization's individual agreement, if any. The list rates are published in the forge_compute section of Get pricing sheet.
  • Monthly cap per server. One server is never charged more than its size's monthly_cap in a calendar month.
  • Parked servers are billed for their stored copy per GB-month (parked_storage.per_gb_month), accrued hourly, instead of the hourly price.
  • Spending limits. Creating or resuming is refused with 402 FORGE_COMPUTE_SPEND_LIMIT_REACHED when the organization's spending limit cannot absorb one more hour. At 90% of the limit every running Aitronos server carries a notice; at 100% running servers are parked (the default) or keep running, as set in the organization's compute settings.
  • Spend limits on Aitronos servers. On top of the spending limit, an organization can set its own monthly limit for Aitronos servers and a default monthly limit per person, someone who manages billing can set a different limit for one person, and each person can hold themselves to a lower one. Get spend limits returns them with this month's spend and every label and sentence to show; change them with Change the organization's limits, Set a member's limit (see List member limits) and Set your own limit. A person's spend is the spend of the servers they own. Creating or resuming past one is refused with 402 FORGE_COMPUTE_SPEND_LIMIT_REACHED (details.reason org_compute_limit_reached or member_limit_reached, checked against the server owner's limit); at 90% of a person's limit their running servers carry the notice member_limit_90, and at 100% they are parked (member_limit_parked) or keep running (member_limit_100). Limits work while Forge cloud compute is switched off.
  • Capacity. Aitronos servers share a platform-wide capacity. When it is reached, creating or resuming an Aitronos server is refused with 503 FORGE_COMPUTE_PLATFORM_CAPACITY_REACHED ("Aitronos servers are at capacity right now. Try again later."), the catalog shows Aitronos servers as blocked with that sentence, and running Aitronos servers may be parked; their work is kept and they can be resumed once capacity is back. Servers on your own cloud accounts are never affected.

Servers in your own account (byo) are never charged by Aitronos. Their prices are the provider's own, in the provider's currency, read with your connected account.

Server lifecycle

StateDriven byMeaning
creatingbackendThe record exists; the server is being created.
bootingbackendThe server exists and is starting.
awaiting_clientclientThe server is running and waits for the client to connect.
securingclientThe client is replacing the bootstrap host key.
installingclientThe client is installing Forge on the server.
pairingclientThe client is pairing with the server.
ready—Usable.
parkingbackendThe server is being saved, then stopped.
parked—Saved and not running.
resumingbackendThe server is being started again from its saved copy.
deletingbackendEverything created for the server is being removed.
deleted—Nothing is left. Listed for seven days.
revokingbackendEmergency stop: the server and its key are being removed now.
revoked—Server and key are gone; the record keeps the reason.
failed_billing—Something went wrong and a server may still exist. Delete it to stop charges.
failed_clean—The server could not be created and nothing is running. failure says why.

Every server response carries state_label (a sentence to show), transient (true while the server is between states) and actions (what the caller may request now, already filtered by what the offering supports). Backend-driven states end on their own: poll until the state changes. Client-driven states (awaiting_client to pairing) end when the client reports its next step, so a client must act on them rather than wait.

Creating and setting up a server

  1. Choose. Pick the organization to bill from List billing organizations, then list compute offerings in it, then get the offering's options and show the person the price of the location and size they pick.
  2. Create. Create a server with a client-chosen id, the chosen organization_id, the person's SSH public key and the quote they confirmed. The answer is 202 with the server in creating, carrying ssh_user (always forge) and ssh_port. bootstrap_host_key_pub is still null in that answer: the bootstrap host key (K0) to trust on the first connection appears on the server record once the backend has generated it, at the latest by awaiting_client. Only public keys are ever stored or returned; the bootstrap key is not a secret handed out once, it is shown on every read until the host key is reported.
  3. Poll. Get the server about every two seconds until it reaches awaiting_client. It moves creating → booting → awaiting_client and gains ipv4/ipv6. A server that could not be created ends in failed_clean with failure.code (for example FORGE_COMPUTE_CAPACITY_UNAVAILABLE with failure.details.alternatives).
  4. Connect on K0. At awaiting_client, connect as ssh_user with the person's key, pinning bootstrap_host_key_pub.
  5. Secure. Report securing. On the server, wait for /var/lib/forge/bootstrap.done, read the staged key K1 from /etc/ssh/forge_next_ed25519_key.pub and pin it, then touch /var/lib/forge/host-key/commit so the server swaps K1 in. Reconnect pinned to K1 and report the host key. From then on host_key_pub is the key to trust and bootstrap_host_key_pub is null.
  6. Install and pair. Report installing, then pairing, as the client reaches them.
  7. Ready. Mark the server ready. This is refused with 409 FORGE_COMPUTE_INVALID_STATE until the host key was reported.
  8. In use. Report activity at most once every five minutes while the server is used. It drives the idle reminder and, if the organization turned it on, automatic parking.

Setup steps only move forward: repeating the current step changes nothing, and an earlier step is refused.

Park, resume, delete, revoke

  • Park saves the server (a snapshot where the offering's capabilities.park is snapshot, or the stopped server itself where it is poweroff), then stops it: ready → parking → parked. Hourly charges stop; the stored copy is billed per GB-month. Offerings whose capabilities.park is false cannot park, and their servers never list park in actions. Aitronos servers are parked automatically after 1 hour without activity (adjustable to 1 to 168 hours in the compute settings, never off), and an Aitronos server left parked for 30 days is deleted (its owner is notified 3 days before; see parked_expires_at).
  • Resume starts a parked server again from its saved copy at a newly confirmed quote: parked → resuming → awaiting_client. The server keeps its host key K1, so the client skips securing, reports installing and pairing, and marks it ready. The saved copy is removed once it is ready.
  • Delete removes the server and everything created for it: deleting → deleted. The record stays and is listed for seven days.
  • Revoke is the emergency stop for a server or key that may be compromised: the server and its SSH key are removed at once (revoking → revoked) and the record keeps the reason. Delete it afterwards to remove what is left. A parked server has no running server to revoke; delete it instead.

Every action answers 202 with the server in its new state, and asking again for a state that is already current returns the server again rather than an error. Park, delete and revoke work while Forge cloud compute is switched off; resume does not, because it starts charges again.

A server's history

Three reads describe what a server has done, for a detail page: Get a server's daily cost and uptime (what it was billed per day, from the same ledger as the usage page, and how long it ran), List a server's running intervals (each period it ran and why it stopped) and List a server's event history (every move through the lifecycle, with a sentence to show). The first two take a period of at most 93 days and default to the current month.

Errors

Every refusal uses the standard error envelope. error.message is a sentence written to be shown to the person as is; branch on error.code. A server that fails after the request was accepted carries the same code in failure.code.

{
  "success": false,
  "error": {
    "code": "FORGE_COMPUTE_INVALID_STATE",
    "message": "This server cannot do that in its current state. Wait for it to finish and try again.",
    "system_message": "Action 'park' is not allowed while the host is 'creating'",
    "type": "client_error",
    "status": 409,
    "details": {"state": "creating", "action": "park"},
    "trace_id": "3f1c9a52-7d4e-4b8a-9c21-6e0d5f7a8b34",
    "timestamp": "2026-09-28T09:00:00Z"
  }
}