Altium - the Altium Bridge
Public Made by Adomby adom
Adom Bridge for Altium Designer: a resident DelphiScript agent gives the AI eval, the 1,100-command process launcher, all 8 EDA surfaces with screenshots, compile/ERC, DRC, OutJob outputs, native SchLib/PcbLib authoring with STEP 3D bodies, and dialog handling by PID.
main
name: altium-a365
description: >-
The Altium 365 cloud lane of the altium-bridge: the eleven altium_a365_* verbs. Store a
workspace and a Bearer token, or sign in with OAuth (PKCE) using an Altium-issued public
client ID; run GraphQL against the workspace; refresh and revoke tokens; read the workspace
library overview and the library-related schema; upload a file to the Files Service. None of
it needs Altium Designer running. Use when the user asks about their Altium 365 workspace,
projects or cloud library, or when a verb returns a365_not_configured. Trigger words — altium
365, a365, altium workspace graphql, altium oauth, altium cloud library, a365 token,
altium_a365_query, altium_a365_oauth_begin.
Parent skill: altium-bridge
altium-a365
The cloud lane talks HTTPS to the workspace directly. It has no Altium Designer dependency: it
works while X2.EXE is closed and none of these verbs is gated on a licence. Tokens live in the
bridge cache (a365.json) and NEVER appear in a verb reply; refresh and the OAuth result
surface only an allow-listed summary of the token's claims.
Two ways to get a token
- Manual token.
altium_a365_configure {workspace, token}stores the workspace domain (e.g.acme.365.altium.com) and a Bearer token created in the workspace web UI under Admin → Developer. Only plans that expose that page have one; the Develop trial does not.workspaceis required the first time; either field can be updated alone later. - OAuth (PKCE, public client).
altium_a365_oauth_begin {clientId, workspace, selectWorkspace?, timeout?}.clientIdmust be an Altium-issued OAuth client ID (issued through Altium's Developer Center enrollment; do not reuse a first-party client ID). Both fall back to the stored values.selectWorkspaceisstrict(default),optionalornone.timeoutis how long the bridge waits for the sign-in, default 300 s.
The OAuth flow
altium_a365_oauth_begin '{"clientId":"<id>","workspace":"acme.365.altium.com"}'
# -> { status:"waiting", authorizeUrl } the bridge is ALREADY listening when this returns
# open authorizeUrl in the user's existing browser; they finish Altium's consent page
altium_a365_oauth_status '{}' # poll: idle | waiting | authorized | cancelled | error
altium_a365_library_overview '{}' # proves the workspace-scoped token
- The bridge starts its wait on Altium's ActionWait endpoint BEFORE it returns
authorizeUrl, so open the URL only after the verb has returned. - One flow at a time: a second
oauth_beginwhile one is waiting returnsa365_oauth_in_progress.altium_a365_oauth_cancelstops a waiting flow (repliesalreadyStopped:truewhen none is waiting); polloauth_statusafterwards. - On
error,oauth_statuscarries anerrorCode:a365_oauth_timeout,a365_state_mismatch,a365_actionwait_gone,a365_actionwait_http,a365_actionwait_shape,a365_token_exchange_failed,a365_network_error. - On success the bridge stores the access token, the refresh token (the scope includes
offline_access), the client ID and the expiry.
Verbs
| Verb | What it does | Args |
|---|---|---|
altium_a365_configure |
store workspace + manual Bearer token | workspace, token |
altium_a365_status |
configured, workspace, hasToken, hasRefreshToken, clientConfigured, endpoint; with a token it also runs a one-row probe query and reports tokenLive + probe |
— |
altium_a365_query |
run GraphQL against https://<workspace>/svc/napi/gateway/graphql/; replies data and errors (success is false when errors is present) |
query (required), variables, timeout (s, default 60) |
altium_a365_oauth_begin |
start the PKCE sign-in, return authorizeUrl |
clientId, workspace, selectWorkspace, timeout |
altium_a365_oauth_status |
state of the current or last flow | — |
altium_a365_oauth_cancel |
cancel a waiting flow | — |
altium_a365_refresh |
exchange the stored refresh token for a new access token; a rotated refresh token is stored too | — |
altium_a365_logout |
revoke the refresh token at Altium, then remove every cached token; if revocation fails the local grant is KEPT and the verb fails | — |
altium_a365_library_overview |
fixed query: the workspace library's name, description, updatedAt, component ids/names, footprint and symbol counts | — |
altium_a365_library_schema |
introspects the schema and returns only the queries and mutations whose names contain lib, component, symbol, footprint, part or datasheet |
timeout |
altium_a365_files_upload |
multipart upload to the workspace Files Service; replies a temporary opaque fileId (expiresAfterHoursInactive: 24) to pass to the matching library mutation |
filePath (required, a path on the bridge's machine), maxBytes (default 100 MB), timeout (s, default 120) |
Error codes to branch on
a365_not_configured (no workspace or token: run oauth_begin or configure),
a365_workspace_required, a365_client_id_required, a365_bad_workspace_selection,
a365_oauth_in_progress, a365_refresh_not_configured (no client ID or refresh token
stored), a365_refresh_failed, a365_revoke_failed, a365_graphql_http (non-200 from
GraphQL; the token has usually expired, so refresh or sign in again),
a365_network_error, a365_file_required, a365_file_not_found, a365_file_too_large,
a365_file_upload_failed.
Rules
library_schemais a read-only map. Choose a mutation only after its input types and its rollback or delete mutation are understood.- Treat
fileIdas opaque and short-lived: do not parse it, do not persist it. - Explore the full schema in a browser at
https://<workspace>/api/voyager.
---
name: altium-a365
description: >-
The Altium 365 cloud lane of the altium-bridge: the eleven `altium_a365_*` verbs. Store a
workspace and a Bearer token, or sign in with OAuth (PKCE) using an Altium-issued public
client ID; run GraphQL against the workspace; refresh and revoke tokens; read the workspace
library overview and the library-related schema; upload a file to the Files Service. None of
it needs Altium Designer running. Use when the user asks about their Altium 365 workspace,
projects or cloud library, or when a verb returns a365_not_configured. Trigger words — altium
365, a365, altium workspace graphql, altium oauth, altium cloud library, a365 token,
altium_a365_query, altium_a365_oauth_begin.
---
Parent skill: **altium-bridge**
# altium-a365
The cloud lane talks HTTPS to the workspace directly. It has no Altium Designer dependency: it
works while X2.EXE is closed and none of these verbs is gated on a licence. Tokens live in the
bridge cache (`a365.json`) and NEVER appear in a verb reply; `refresh` and the OAuth result
surface only an allow-listed summary of the token's claims.
## Two ways to get a token
1. **Manual token.** `altium_a365_configure {workspace, token}` stores the workspace domain
(e.g. `acme.365.altium.com`) and a Bearer token created in the workspace web UI under
Admin → Developer. Only plans that expose that page have one; the Develop trial does not.
`workspace` is required the first time; either field can be updated alone later.
2. **OAuth (PKCE, public client).** `altium_a365_oauth_begin {clientId, workspace,
selectWorkspace?, timeout?}`. `clientId` must be an Altium-issued OAuth client ID (issued
through Altium's Developer Center enrollment; do not reuse a first-party client ID). Both
fall back to the stored values. `selectWorkspace` is `strict` (default), `optional` or
`none`. `timeout` is how long the bridge waits for the sign-in, default 300 s.
## The OAuth flow
```bash
altium_a365_oauth_begin '{"clientId":"<id>","workspace":"acme.365.altium.com"}'
# -> { status:"waiting", authorizeUrl } the bridge is ALREADY listening when this returns
# open authorizeUrl in the user's existing browser; they finish Altium's consent page
altium_a365_oauth_status '{}' # poll: idle | waiting | authorized | cancelled | error
altium_a365_library_overview '{}' # proves the workspace-scoped token
```
- The bridge starts its wait on Altium's ActionWait endpoint BEFORE it returns
`authorizeUrl`, so open the URL only after the verb has returned.
- One flow at a time: a second `oauth_begin` while one is waiting returns
`a365_oauth_in_progress`. `altium_a365_oauth_cancel` stops a waiting flow (replies
`alreadyStopped:true` when none is waiting); poll `oauth_status` afterwards.
- On `error`, `oauth_status` carries an `errorCode`: `a365_oauth_timeout`,
`a365_state_mismatch`, `a365_actionwait_gone`, `a365_actionwait_http`,
`a365_actionwait_shape`, `a365_token_exchange_failed`, `a365_network_error`.
- On success the bridge stores the access token, the refresh token (the scope includes
`offline_access`), the client ID and the expiry.
## Verbs
| Verb | What it does | Args |
|---|---|---|
| `altium_a365_configure` | store workspace + manual Bearer token | `workspace`, `token` |
| `altium_a365_status` | `configured`, `workspace`, `hasToken`, `hasRefreshToken`, `clientConfigured`, `endpoint`; with a token it also runs a one-row probe query and reports `tokenLive` + `probe` | — |
| `altium_a365_query` | run GraphQL against `https://<workspace>/svc/napi/gateway/graphql/`; replies `data` and `errors` (`success` is false when `errors` is present) | `query` (required), `variables`, `timeout` (s, default 60) |
| `altium_a365_oauth_begin` | start the PKCE sign-in, return `authorizeUrl` | `clientId`, `workspace`, `selectWorkspace`, `timeout` |
| `altium_a365_oauth_status` | state of the current or last flow | — |
| `altium_a365_oauth_cancel` | cancel a waiting flow | — |
| `altium_a365_refresh` | exchange the stored refresh token for a new access token; a rotated refresh token is stored too | — |
| `altium_a365_logout` | revoke the refresh token at Altium, then remove every cached token; if revocation fails the local grant is KEPT and the verb fails | — |
| `altium_a365_library_overview` | fixed query: the workspace library's name, description, updatedAt, component ids/names, footprint and symbol counts | — |
| `altium_a365_library_schema` | introspects the schema and returns only the `queries` and `mutations` whose names contain lib, component, symbol, footprint, part or datasheet | `timeout` |
| `altium_a365_files_upload` | multipart upload to the workspace Files Service; replies a temporary opaque `fileId` (`expiresAfterHoursInactive: 24`) to pass to the matching library mutation | `filePath` (required, a path on the bridge's machine), `maxBytes` (default 100 MB), `timeout` (s, default 120) |
## Error codes to branch on
`a365_not_configured` (no workspace or token: run `oauth_begin` or `configure`),
`a365_workspace_required`, `a365_client_id_required`, `a365_bad_workspace_selection`,
`a365_oauth_in_progress`, `a365_refresh_not_configured` (no client ID or refresh token
stored), `a365_refresh_failed`, `a365_revoke_failed`, `a365_graphql_http` (non-200 from
GraphQL; the token has usually expired, so `refresh` or sign in again),
`a365_network_error`, `a365_file_required`, `a365_file_not_found`, `a365_file_too_large`,
`a365_file_upload_failed`.
## Rules
- `library_schema` is a read-only map. Choose a mutation only after its input types and its
rollback or delete mutation are understood.
- Treat `fileId` as opaque and short-lived: do not parse it, do not persist it.
- Explore the full schema in a browser at `https://<workspace>/api/voyager`.