How a source talks to sandcastle
A source is a service that has work for sandcastle: an HTTP API you write, inside your network or on the internet. This page explains how the two talk and why. The exact calls are in The source contract.
sandcastle starts every exchange
sandcastle listens on no port. It asks a source for work, and a source never calls it. So a source needs no way into the machine that runs sandcastle, and nothing on the internet can hand sandcastle a job unless the operator configured it as a source.
To the source, sandcastle is a worker with a token: requests that carry
Authorization: Bearer <token>. The operator sets the token as a secret, and only the keep ever
holds it.
A job carries everything
sandcastle knows nothing about a source’s data. A job is self-contained: it names one capability and holds that capability’s input, and nothing else is read. A source that wants a note tagged sends the note and the question in the job; it cannot point sandcastle at a file, a URL or another service.
The capabilities are fixed, and so is what each takes and gives back: see Capabilities. A source cannot choose a program, a model or an argument. The operator chose them.
The life of a job
- The core asks the source for jobs, naming the capabilities the operator allowed for it and that are not resting. It asks for one job at a time.
- The source hands out a job and holds it for this worker for as long as it decides.
- A box runs the job: made for it alone, with no network and no secret, and gone when the job ends.
- The core sends the result back to the source that handed the job out, under the job’s id:
succeeded, with the output;failed, with the error: the job itself is at fault, so offering it again is pointless;released: not now, and not the job’s fault. The capability could not be used, so the source should offer the job again later, without counting an attempt.
sandcastle trusts the source no more than the job
Every source is treated as hostile, even one you wrote. sandcastle never follows a redirect, reads only the fields of the contract, and keeps each source’s jobs, results and token apart from every other source’s. A source cannot learn another source’s token, see another source’s jobs or send sandcastle anywhere else.
The source should return the favour. An output is what a box made from the job’s content, and that content may be hostile: a model can be talked into a reply that looks like an instruction. Treat every output as untrusted, and check it has the shape you asked for before you use it.
How often a source is asked
- One job runs at a time, across all sources. A slow job delays the others.
- Each source is asked every
poll_interval. max_jobs_per_hourcaps how many of its jobs run in an hour. When it is reached, nothing more is claimed from it until the hour moves on.- A source that cannot be reached is asked again later each time, up to every 10 minutes. It never holds the others back.
- When the keep is down, or the source’s secret cannot be used, the source is left out of that
round and asked again at its
poll_interval.
These keys are in config.yaml.