a9script

Product

Everything it does

The complete list. Each sentence links to the documentation page that explains it, where that page exists; how we know each is true is said once, at the foot.

Configured calls

A call to another system is configured once, given a name in your words, and called from a script by that name — FindContact({ email }). The connection, the credential, the retries, the pause when the far end says not now and the record of the request all belong to the configuration, not to the script.

Read it

The kinds of configured function are http, text, email, csv, jsonmap and llm. A script calls each by name; http, text, email and llm take named parameters, csv and jsonmap take the one value they convert.

Read it

A parameter is a value, never structure: {{param}} is encoded for the place it sits in and cannot become a second header, query parameter or body field.

Read it

You say which statuses count as an answer (expect) and what the answer is (answer): a value at a path, one element, or null for absence. Anything else stops the run and reports the far end's status, its body and how often the call was repeated.

Read it

A transient failure is repeated on the spot; by default 400, 401, 404 and 422 are never repeated, and on an OAuth or JWT connection a 401 refreshes the token once and re-sends. Name a status as a long wait — 429 is the usual one — and the whole run is parked for the time the far end asked, holding nothing open.

Read it

One wait is at most 24 hours; a longer request is cut to that, and both numbers are written into the run's log.

Read it

Paging is configuration — next-link, cursor or offset. One line of script reads every page into a dataset and keeps its place across a throttle.

Read it

Outgoing authentication is part of the connection: basic, bearer, an API key in a header or query parameter, OAuth 2 client credentials or refresh token, or a signed JWT assertion. On OAuth 2 and JWT connections a 401 refreshes the token once and re-sends the call, never in a loop.

Read it

Test runs the definition as it is on screen, unsaved, and shows what a script gets and the request that was sent — the credential named, never shown.

Read it

A call goes to its connection's address only; a path or continuation link that would leave that address is refused.

Read it

When a bot-check page answers instead of the API, the platform says so and names it; it never tries to solve the check. Known guard headers are recognised on any status, and an HTML page is recognised wherever your call declared what data it expects.

Read it

Every function is classified as reading or writing from its own definition; the explorer marks the ones that write.

Read it

A public HTTP API is reached through an http function: method, path, headers and a JSON body with {{param}} values. A GraphQL API is called the same way — a POST whose body carries the query and its variables.

Read it

An llm function sends a prompt through a connection that holds the API key and reaches Anthropic models; a demo provider answers deterministically without a key. A model's answer is input for the script to validate.

Read it

Outbound mail goes through SMTP or Microsoft Graph, with attachments; the script never holds the password.

Read it

A mail account sends, redirects every recipient to your inbox with the original recipients in headers, or records the mail only. The run takes the same path in every mode and says which happened.

Read it

Scripts and runs

The configured calls complete in the script editor and show, on hover, what they take and what they answer — before anything is activated. A name that resolves to nothing is marked while you type.

Read it

A script is plain JS: it reads input, calls functions and returns a value. There are no modules and no async keywords.

Read it

A construct the language does not allow is refused before the run, with the construct, its line and its column named.

Read it

A run starts from a webhook, from an API call that waits for the answer, from a schedule (UTC cron), from a message arriving in a mailbox, from a failure in the environment, or on demand from the Test button or the command line.

Read it

Shared code goes into library scripts, linked in order. Environment values go into one settings script whose result reaches every script as input.settings.

Read it

Every function a script can call is documented once, from one source, and that source produces the reference, the Help panel and the editor's hover text.

Read it

Every edit goes into one draft. Activate saves the draft as one step, and every Activate is a numbered version. Only the on/off switch takes effect at once.

Read it

Two authors cannot overwrite each other: one browser window edits an environment at a time. A second window is read-only and can take the lock over from the badge; after that, the first window's Activate is refused.

Read it

Every step of a run is written down before the next one starts. After a restart, a deployment or a lost machine, the run continues from its last saved point on another machine. A call it already made is never repeated. A run interrupted in the middle of a call is stopped and reported rather than re-sent, unless that function is marked safe to repeat.

Read it

A run cannot catch its own kill switch: try/catch never catches the platform ending a run that is out of time, steps or values. Time is budgeted per segment — checkpoint() starts the next segment with a fresh time budget — while steps and values are counted over the whole run.

Read it

Every dispatched run executes in its own supervised process with a memory cap and a time limit per segment. A run that exceeds either is killed and its outcome recorded.

Read it

The integration store holds id mappings, small durable state and named datasets per environment, outside the run.

Read it

Bulk work does one bounded piece at a time and keeps its place across a pause. The published sync recipes are executed in the test suite against two simulated systems on every build.

Read it

Dataset transforms map records, enrich one lookup per row and detect duplicates without repairing them. By default a bad row goes to <name>.rejected with its key and reason and the job continues; you choose onError: "fail" if a bad row should stop it.

Read it

CSV emitted under a size cap never splits a record, and the far end's line number joins back to the record that wrote it.

Read it

A PDF is built from a block list or from markdown — one document model. Markdown can be rendered to HTML, sanitised, escaped or stripped.

Read it

A script holds a file handle, never bytes. File stores hold files by path, with per-file, per-store and per-environment ceilings.

Read it

Every script sample in the documentation is executed against the product before a release. The operator pages are backed by automated browser walks that perform what the page describes.

Read it

A settings script that reads fine but answers no value is flagged as a warning — in the editor, on Activate and in the apply output — so it cannot go unnoticed. The warning reports; it does not block.

Read it

Endpoints

A parameter structure describes the shape of a JSON value once, by name. An API endpoint checks a caller's arguments against it before a run starts; it never converts a value and never echoes one back.

Read it

One accepted event runs at most once. For senders that send a delivery id, a repeated delivery is dropped at the endpoint.

Read it

A webhook endpoint acknowledges the sender at once and runs your script afterwards. A synchronous API endpoint waits for one script's respond() and tells the caller 404, 500 or 504.

Read it

An endpoint is read as a webhook, an API, an MCP server or an app — over the same path, network rule and switch. The three script-facing kinds share the endpoint's credential; an app endpoint serves its files to a browser and carries no credential of its own.

Read it

Each operation is public, for signed-in callers, or for a list of roles. The tool table narrows to what the caller may reach; an unknown operation and one the caller may not reach answer alike.

Read it

Every activated endpoint describes itself. The browser, a9script describe and a GET on the endpoint answer the same document.

Read it

Incoming authentication: none, bearer, basic, signed (HMAC), JWT, AWS SNS or a shared secret. A signed endpoint verifies against the sender's replay window where the sender sends a timestamp, and accepts the previous secret during a rotation.

Read it

Pick your sender — a9script, AWS SNS, GitHub, Jira, Linear, Microsoft Graph, Okta, Shopify, Slack, Standard Webhooks, Stripe, Twilio, Xurrent, Zoom — and the verification recipe is filled in; you enter only the secret or the trust anchor. A sender not in the list is described in the same vocabulary as a custom recipe.

Read it

Registration handshakes (Microsoft Graph, Slack, Okta, Zoom, AWS SNS, Xurrent) are answered by the platform without a run.

Read it

List the networks an endpoint accepts, and every other address gets the same refusal as a wrong credential. A sender whose profile publishes its ranges (Linear today) has them merged in. An endpoint whose only credential is a network range is refused until you acknowledge that choice. Behind a reverse proxy, name the trusted proxy so the caller's address is the real one.

Read it

Several scripts can listen on one webhook endpoint, each with its own when filter, so each receives only the events it asked for. An event no script takes is counted and logged, never lost silently.

Read it

Give a connection your own identity in that system and add ignore rules to a webhook endpoint: your own writes coming back are dropped before any script runs — the usual cause of a two-way sync feeding itself. Only a matching rule drops an event; anything else still runs.

Read it

An API or MCP endpoint can require a signed-in caller. You invite app users by email through your environment's own mail account, give them the roles your environment defines, and your script sees who called as input.caller (id, email, roles).

Read it

Incoming requests are bounded: a request body cap (1 MB by default) and rate windows per tenant and per endpoint (1200 and 600 requests per minute by default, set by the operator). Over the window a caller gets 429 with a Retry-After header; over the cap, 413.

Read it

A message arriving in a Microsoft 365 (Graph) or IMAP mailbox starts your scripts — each message once, even across re-scans and restarts.

Read it

A folder of files is served at your app's address and signs users in at your environment.

Read it

MCP

The calls you configured against an HTTP API become an MCP server: an endpoint set to MCP lists operations that name your configured functions or scripts. An MCP client lists and calls them, and each tool's input schema is generated from the parameter structure you declared.

Read it

A tool call runs on the ordinary path and answers within the synchronous budget. A run that would have to wait is stopped and the client is told.

Read it

The authoring surface speaks MCP: a URL and a bound token. Every command that crosses it is a tool (login, setup and files stay on the terminal by decision); an undeclared argument is refused.

Read it

The MCP authoring surface answers the protocol versions a real client speaks.

Read it

The command line and agents

Every command answers JSON under --json. Exit codes are 0 ok, 1 error, 2 validation; an unknown flag is refused with exit 2.

Read it

A folder is the integration: one JSON file per entity, names never ids. apply --dry-run lints without writing; apply never deletes.

Read it

The a9script authoring skill teaches an AI agent the whole loop — look at the environment, probe a call, write the files, lint, apply, run with a trace, inspect, fix, step through. Its command lists, function types, refusal codes and example scripts are checked against the product on every build, so what the skill teaches is what the product does.

Read it

A test in the gate builds a two-system integration against real services using only the commands and flags the authoring skill teaches — a session that cannot use a word the skill does not contain.

Read it

A probe fires one configured call ad hoc and shows the request as sent and the far end's own answer. A write needs the environment's switch AND an acknowledgement, and is audited.

Read it

A sandbox debug run keeps every outbound request and each attempt's response (bodies capped at 256 KB, marked when cut) for seven days by default. The credentials the platform attaches are shown by name, never by value.

Read it

A stepped run parks after every external call. Its position shows the pending call, the current statement and bounded previews of the variables. Abort before the third call and the far end has seen exactly two — pinned by the command line's stepped-session and agent-loop tests.

Read it

Debug, step and probe exist only in a sandbox; production refuses them before anything runs.

Read it

A misspelled command-line flag or MCP tool argument is refused, so a typo can never turn a dry run into a real apply.

Read it

Operations

Work is queued fairly across tenants. A delivery that cannot become a run after five attempts becomes a dead letter you can read and discard.

Read it

When a connection's calls meet transport faults or 5xx answers in a row, further calls are refused with a message that names the connection, how long the circuit has been open, the count, the route that counted and the next probe. The connection turns red until acknowledged.

Read it

Every tenant runs under ceilings: queued work per tenant, stored bytes per environment, and outbound calls and mails per environment. A refusal names the platform's own limit.

Read it

Health latches. Red means something is not working: a failed, timed-out or killed run, or an error your script logged. Amber means something worth knowing: a warning your script logged, or a credential the far end granted narrower than asked. Both stay until you acknowledge them.

Read it

Notification rules mail you, throttled (five per hour by default), with the swallowed count in the next mail. System triggers start a script of your own.

Read it

One run log per script. Search terms are ANDed, a level means that level and above, a time window slides, a run id replaces it. The platform logs its own calls with names, argument keys, row counts and outcome; an argument's value is never written — the one exception is a mail account set to record, which writes the withheld message so you can read what would have been sent. Older runs past the retention window are read one run at a time.

Read it

Queue operations: read the lanes, hold a run so it is never archived away, stop a running run, discard a dead letter, replay a logged event as a new one. Every act answers what actually happened — a run that had already finished says so, a message no longer there says so.

Read it

Turning off a script, connection, function, mail account or notification rule is honoured everywhere the platform acts — dispatcher, outbound calls, pollers, endpoints. A webhook arriving at a switched-off endpoint is still acknowledged, so the sender does not keep retrying.

Read it

The dashboard never invents a number: with no runtime attached it says so, and durations appear only for windows with a completed run.

Read it

The product runs as two processes on one box with one volume; a backup is taken while it runs.

Read it

Security

A token names one tenant and one environment when it is minted and always expires (14 days at most by default, set per installation). It cannot change connections or other credential-bearing entities unless minted with that permission, and it can never mint a successor with more rights than itself.

Read it

Sandbox and production are sealed off from each other; nothing in one reaches the other except a promotion you perform yourself. Production says so in colour, and activating or deleting there asks first, naming where you are.

Read it

Promotion shows a plan first — new, update, up to date, once-only, changed in target — with dependencies resolved by name. A credential never crosses.

Read it

History, diff, blame and restore: a secret is reported as changed, never shown. A restore is a new version.

Read it

There is no default administrator; the first account is created from a one-time setup token.

Read it

The roles are Administrator, Tenant admin, Specialist and Auditor. A grant is visibility: what you are not granted answers not found.

Read it

Second factor: TOTP with recovery codes, required for everyone by default in a production deployment, with a lockout on the verify step and an administrator reset for a lost factor.

Read it

Browser sessions end after 30 minutes idle or 12 hours absolute (both defaults an operator can shorten). When a session ends, the login screen says which limit signed you out.

Read it

A secret is entered once, encrypted at rest, and bound to its tenant, environment, entity kind and field; ciphertext copied from elsewhere does not open. No screen, command, diff or recorded request returns a value, and the part of the platform you author in has no path that reads a secret back — the only place one is opened is the key-rotation pass, which re-encrypts inside itself and never exposes the value.

Read it

Registered secrets are encrypted at rest. Scripts, configuration, run records and datasets are stored in plain form on the volume — encrypting the disk is the operator's job.

Read it

Cloud metadata addresses are refused always. Private address space is denied unless a tenant admin allows ranges. Every socket is judged at connect and pinned to the judged address.

Read it

Every call carries a User-Agent naming a9script and its version, and the status page reports the outbound address your operator configured, so a partner can allow-list it.

Read it

Both audit trails are append-only and hash-chained: a changed or removed row is detectable. Policy switches are recorded at the moment they change.

Read it

Deleting a tenant removes configuration, history, credentials, runs, files and staged data on every machine of the installation, and is reported finished only when every machine has confirmed. The audit trail survives, and a backup taken before the deletion restores the tenant whole.

Read it

Builds are security-scanned: dependency audit, secret scan, static analysis, a software bill of materials and an image scan.

Read it