Six ideas explain everything else in these docs: the pipeline, the operators you build it from, how encryption stays on through the whole run, the two keys, the two credentials, and the worker that runs your work.
A pipeline is your computation, written so it can run on encrypted data. It is the unit you build, deploy, and query. It behaves like a model: defined once, then run many times.
Every pipeline has three parts, fixed at build time:
Your machinePreprocessPrepares and encrypts your input before it leaves.
WorkerBodyThe main computation, run on ciphertext by the worker.
Your machinePostprocessDecrypts the result and shapes it back for you.
Runs on your machineRuns on the worker, encrypted
Preprocess and postprocess run where your data is, so encryption and decryption never leave your side. The body runs remotely, on data that stays encrypted the whole time. You define all three when you build the pipeline.
HomOps are the operators you build a pipeline from. Each one is shaped like a standard ML operation: a linear layer, an activation, and a matrix multiply each have a homomorphic counterpar. HomMatMul plays the role of MatMul, and so on.
Each operator also carries parameters an ML op wouldn't need, since it operates on a ciphertext rather than a plaintext tensor: for example pt_scale, which sets the precision the plaintext weight is encoded at. A few HomOps, like HomModSwitch and Bootstrap, exist only to maintain the ciphertext (refreshing its level or noise budget) and have no ML counterpart at all.
Either way, the pipeline stays simple. You arrange operators into the pipeline. You do not write cryptography. Each operator applies it for you.
The full set of operators, what each does, and where it runs is in the HomOps Reference.
Your data is encrypted the entire time it is off your machine. Your input is encrypted before it leaves your machine. The worker runs the body of your pipeline directly on that ciphertext. It computes a correct, encrypted result without ever decrypting your data. The result comes back encrypted, and only you can read it.
You
encrypt the input, decrypt the result
query · ciphertext
result · ciphertext
Worker
computes on ciphertext, never sees plaintext
Your plaintext never leaves your machine. The platform only ever sees ciphertext, never the data behind it. The same is true on every query.
Encryption needs two keys, and they live in two different places. One stays with you. The other goes to the server.
Stays with you
Secret key
Encrypts your input and decrypts the result. It never leaves your machine. Without it, no one can read the result, including the server.
Goes to the server
Evaluation key
Lets the worker compute on your ciphertext without decrypting it. It is uploaded once and used by the worker during a query. It cannot read your data.
Key generation takes longer than a query does, but only happens once. Every query after that reuses the same keys.
Both keys are generated on your side when you call generate_key() during Key generation, after the worker is up. The query client sends the evaluation key to the server and keeps the secret key locally. Later query runs load that key with generate_key(load_if_exists=True).
A worker is the accelerator that runs the body of your pipeline on ciphertext. It is not always on. You start one to run queries and stop it when you are done.
You pay for worker time, not per query. A running worker uses credits for as long as it is up, however many queries you send through it. Start it, run what you need, stop it. Credits cover the runtime in between.