Skip to main content
Stage 4 · Query

Run queries

Your pipeline is deployed, and keys are already generated. Now you run encrypted queries against it. Start a worker, load the existing key, send as many queries as you need, then stop the worker. The worker only ever receives ciphertext, so your input and result stay private.

Start, load key, query, stop​

Querying is a loop with a clear start and end. You turn a worker on, load the key you generated in Key generation, run queries while it is up, and turn it off when you are done.
Start worker
Turn the worker on when you are ready.
credits begin
Load existing key
Call keys.ensure() to reuse the local key and load the registered EVK on the worker.
×N
query.encrypted()
Send a query, get a result. Repeat as many times as you want.
while worker is up
Stop worker
Turn it off when your work is done.
credits stop
You pay for the worker's runtime, not per query

Start the worker​

A worker runs the body of your pipeline. Start it with the model_id from deploy. It uses credits from this moment until you stop it, so start it when you are ready to query.
query.pyPYTHON
# credits begin here
with studio.workers.running(model_id, stop_on_exit=True):
    # load key and run queries inside this block
    ...

Load the existing key​

Create a query client with the access token from Key generation, then call client.keys.ensure(). It reuses the key artifacts already on your machine; it does not generate or upload a second evaluation key. After the worker starts, it loads the evaluation key already registered for this model. You installed the query client with Lattica Studio at setup. In a researcher setup, that is the same environment you deployed from.
query.pyPYTHON
from lattica_query import QueryClient

token = studio.tokens.load("MY_MNIST_MODEL")
with QueryClient(token) as client:
    # reuse local key artifacts; the worker loads the registered EVK
    key = client.keys.ensure()
Load the token with studio.tokens.load using the same model_name you saved. keys.ensure() returns the local key your queries need. If the worker has just started, the client also makes sure the registered evaluation key is ready on its GPU.

Run a query​

client.query.encrypted(...) encrypts your input, runs it on the worker, and decrypts the result for you. The complete snippet keeps key loading and encrypted inference inside the worker session. Your plaintext never leaves your machine.
query.pyPYTHON
from lattica_query import QueryClient

token = studio.tokens.load("MY_MNIST_MODEL")
with studio.workers.running(model_id, stop_on_exit=True):
    with QueryClient(token) as client:
        key = client.keys.ensure()
        # run as many times as you need while the worker is up
        result = client.query.encrypted(x, key=key)
        y_pred = result.argmax(dim=-1)
Inside that one call, three things happen:
Encrypt
Your input is encrypted on your machine. It is packed into slots first, and the last block is filled with zeros.
ciphertext
Run on worker
the worker computes on ciphertext
ciphertext
Decrypt
the result is decrypted, just for you
Run it again with a different input as often as you like. The worker stays up between queries, so each one is a single call.

Stop the worker​

When you are done, stop the worker. Credits stop the moment it goes down. If you used studio.workers.running(..., stop_on_exit=True), the worker stops when the block exits.
query.pyPYTHON
# credits stop when the context exits (stop_on_exit=True)
studio.workers.stop(model_id=model_id)

Leave the worker running only while you need it. Billing is by runtime, so a worker left up keeps using credits even when idle. Start it for a session of queries, then stop it.

The full flow​

That completes the path: from a plaintext input to an encrypted answer and back, after deploy and key generation.
Build → Deploy → Key generation → Query

Next​

See it all together

End-to-End Example

One runnable walkthrough that threads build, deploy, key generation, and query in a single script.

→