function.py: source bundle, install command, entrypoint, env
var names, optional service port, declared outputs, and runtime policy.
Nullspace creates Function versions, job runs, service instances, logs, output
metadata, and backing machines.
Use this path when the agent is part of your product workflow and your
application wants to call it repeatedly. Your backend stays the control plane
for users, auth, billing, product data, and business rules. Nullspace is the
compute plane for the agent process: isolated machines, deploy/run records,
endpoint traffic, logs, outputs, and retained debugging access.
Current live modes are job and service. Nullspace run IDs are not
conversation session IDs.
Lifecycle
- Create
function.pywithnullspace functions init. - Select project files with
bundle=nullspace.Bundle(...)when inference is not enough. - Iterate locally with
nullspace dev. - Deploy the project with
nullspace deploy. - Run a finite job or start a service endpoint.
- Inspect logs, status, outputs, and the backing machine.
- Retain failed machines when you need PTY, SSH, desktop, command, or file debugging.
- Deploy a new version, roll back, or delete the Function when it is no longer needed.
Feature Surface
| Area | What is available |
|---|---|
| Authoring | function.py, nullspace.Function(...), Python and TypeScript projects, explicit bundles, custom templates, warmup hooks, resources, policy, debug retention, outputs, and max concurrency. |
| Deployment | nullspace deploy, nullspace functions deploy, dry-run bundle plans, build cache controls, version history, git SHA provenance, and forward-only rollback. |
| Jobs | run, spawn, map, route selection, runtime env overrides, idempotency keys, bounded concurrency/backpressure, logs, outputs, cancellation, and backing machine access. |
| Services | Service URL lookup, readiness checks, public URL policy, runtime env overrides, restart/stop, logs, checkpoint/branch, and backing machine access. |
| Routing and triggers | Named routes, cron schedules, period schedules, inbound HMAC webhooks, trigger fire history, and route-specific trigger targets. |
| Security and environments | Named Function secrets, request-time env values, dev/staging/prod environments, edge proxy-auth tokens for service endpoints, and app-owned bearer-token checks. |
| Operations | List/get/delete Functions, inspect status, follow logs, retain failed machines, checkpoint runs/services, branch runs/services, lineage trees, rollback, and Machine+Function composition. |
Setup
From a local project directory:uv pip install "nullspace-sdk[cli]" is equivalent after the environment is active.
For CI or non-interactive deploys, use NULLSPACE_API_KEY or
NULLSPACE_TOKEN with NULLSPACE_API_URL instead of auth login.
How Functions Fit Your App
For a product backend, a Function is a named agent endpoint. The backend stores the Nullspace Function name, calls the SDK or API with a server-side API key, and maps application concepts like user IDs, tasks, or conversations to Function run IDs or service instance IDs. Use a job for one-shot work:Environments And CI
Function environments scope Function names, named secrets, version history, and name-based run/spawn/rollback lookups. Omitted environment selectors usedefault.
--env NAME=value remains a runtime env-var override. A bare --env staging
or --environment staging selects the Function environment for commands that
resolve a Function by name. CI jobs can set NULLSPACE_ENVIRONMENT from the
branch or workflow matrix and run the same nullspace deploy command for dev,
staging, and prod. Deploy records the local git SHA on the Function version
when the checkout has one; nullspace functions history and the console
version table show that provenance.
For a complete GitHub Actions workflow, see
examples/github-actions/functions-deploy.yml in the repository.
What You Deploy
nullspace functions init writes function.py. Keep runtime secret values
out of this file; store env var names, named secret references, and non-secret
configuration.
For a finite job:
function.py
mode = "service" and bind the process to
0.0.0.0:
function.py
Definition Fields
Thefunction.py descriptor is the source of truth for deploy behavior:
| Field | Purpose |
|---|---|
name / mode | Stable Function name and job or service runtime shape. If mode is omitted, a service block or routes infer service mode; otherwise the default is job. |
template / workdir | Machine template or template builder plus the working directory inside the guest. |
install / warmup / entrypoint | Dependency install command, optional deploy-time warmup command, and runtime command. |
bundle | Included and excluded local files for upload. |
env / secrets | Required/optional env var names and named secret references. Values stay out of function.py. |
resources / policy | CPU, memory, disk, timeout, internet/public URL, egress, volume, desktop, PTY, debug, and maximum resource policy. |
outputs / debug | Output files/directories to publish after jobs and failed-run machine retention defaults. |
service | Service port, readiness check, and idle timeout for long-running HTTP processes. |
routes / schedules | Named entrypoints and cron/period triggers. |
max_concurrency / requires_proxy_auth | Per-Function admission cap and edge-enforced endpoint credentials for public services. |
function.py
Named Routes
Routes let one Function expose multiple job entrypoints or endpoint paths while sharing the same bundle, version history, secrets, templates, and environment. Every route path starts with/. A route can reuse the default entrypoint or
override it with a route-specific command.
function.py
TypeScript Projects
TypeScript Functions use the samefunction.py descriptor. Use
package.json scripts for the Node build lifecycle:
- Jobs build during
installand run the compiled artifact withentrypoint="node dist/index.js". - Services use
scripts.startandentrypoint="npm run start"with a declarednullspace.Service(port=...). nullspace devcan usetsx src/index.tsfor local iteration; production deploys should not depend ontsx.
function.py
nullspace functions init detects an existing Node package and can scaffold a
minimal TypeScript job with src/index.ts, tsconfig.json, package.json
build/dev scripts, and this shared descriptor.
Invoke a deployed TypeScript Function with @nullspace/sdk:
client.functions.call("fnrun_...") to rehydrate a detached call when only
the persisted run/call ID is available. FunctionRun.wait(), logs(),
outputs(), and cancel() operate on the backing run handle.
Templates And Warmup
Use a named template ref for simple functions, or provide aTemplate builder
when the Function needs a custom machine environment. Deploy publishes the
builder through the existing template pipeline and stores the built canonical
template ref on the Function version.
function.py
install
and before the version is finalized. Named Function secrets are not injected
into warmup commands, so keep secret-dependent downloads in runtime code or a
reviewed non-secret build path.
Run A Job
Usejob when the agent has finite work: code review, report generation,
benchmarking, data extraction, evaluation, or a one-shot framework run.
run invokes the Function and waits briefly for a terminal result. Long work
returns a detached call with the backing run id. Use spawn when you always
want the detached handle immediately.
Set max_concurrency in function.py to cap concurrent job runs for a
Function. run and invoke fail fast with 429 capacity_exceeded plus a
Retry-After hint when the cap is saturated. spawn returns a detached call;
when admitted to the bounded backlog, the call includes queued_reason and
retry_after_seconds.
--version-id or SDK version_id= when you need to run a specific ready
version instead of the active head. Use --idempotency-key or SDK
idempotency_key= when retrying a create request after a client-side timeout.
Schedules And Inbound Webhooks
Schedules and inbound Function webhooks are thin triggers: each fire creates a normal Function run through the same invoke path andmax_concurrency
admission rules. They only target deployed Functions.
Add schedules in function.py:
function.py
Cron is wall-clock stable across redeploys. Period starts from the latest
deploy, so use Cron when the real-world firing time matters.
Operate schedules from the CLI or SDK:
input["webhook"]["payload"].
Lifecycle webhooks under nullspace lifecycle webhooks ... are outbound
machine lifecycle subscriptions; they are separate from inbound Function
webhook triggers.
The CLI covers the common trigger lifecycle: create, list, manual fire, and fire
history. The API reference also exposes get, update, and delete operations for
individual schedule and webhook trigger records.
Start A Service
Useservice when the agent exposes HTTP, WebSocket, or another long-running
server: an API wrapper around a graph, a web preview service, a chat backend,
or a custom coordinator.
url starts the latest active service when no service instance exists. Pass
--service fnsvc_123 to resolve an existing service instance, and pass runtime
env values only when a new service is being started.
Secure Endpoint Traffic
Setrequires_proxy_auth=True when a public Function service endpoint should
require Nullspace edge credentials before any request reaches the Function
process:
function.py
Nullspace-Key and Nullspace-Secret are stripped before proxying.
Missing, revoked, expired, wrong-route, or wrong-secret credentials return
401 at the edge.
Operate tokens with the same Function reference and environment selector:
Authorization: Bearer ... header in your FastAPI, Express, or other app
server, and leave Nullspace proxy-auth out of that decision path.
Operate A Function
Keep the function name stable. Deploy new bundles from the same project, then use run or service IDs for individual executions.| Need | Command |
|---|---|
| List Functions | nullspace functions list --env prod --json |
| Inspect a Function | nullspace functions get <name> --env prod --json |
| View version history | nullspace functions history <name> --env prod --json |
| Roll back to a version | nullspace functions rollback <name> --version-id fnv_123 |
| Inspect raw event history | OpenAPI GET /v1/functions/{function_id}/events |
| See logs | nullspace functions logs <name> --run fnrun_123 |
| Read output metadata | nullspace functions outputs <name> --run fnrun_123 |
| Check status | nullspace functions status <name> --run fnrun_123 |
| Inspect backing machine | nullspace functions machine <name> --run fnrun_123 |
| Run a debug command | nullspace shell <name> --run fnrun_123 --cmd "ls -la" |
| Cancel a job run | nullspace functions stop <name> --run fnrun_123 |
| Stop a service | nullspace functions stop <name> |
| Retain a stopped service machine | nullspace functions stop <name> --service fnsvc_123 --retain-machine |
| Restart a service after deploy | nullspace functions restart <name> |
| Mint endpoint proxy-auth | nullspace functions proxy-auth create <name> |
| List endpoint proxy-auth | nullspace functions proxy-auth list <name> |
| Revoke endpoint proxy-auth | nullspace functions proxy-auth revoke <name> <token_id> |
| List schedules | nullspace functions schedule list <name> |
| Inspect trigger fires | nullspace functions schedule fires <name> |
| List inbound webhooks | nullspace functions webhook list <name> |
| Delete a function | nullspace functions delete <name> --yes |
Checkpoint, Branch, And Rollback
Function checkpoints capture the backing machine for a live run or service instance. Use them to branch experiments from captured machine state, inspect lineage, or roll back the active Function target.Logs, Outputs, And Machines
Function jobs and services expose backing machine IDs. Use normal machine tools to inspect files, run commands, open PTY sessions, create snapshots, or destroy retained debug machines.Secrets And Env Vars
Declare env var names withnullspace.Env. For reusable credentials, create a
named secret and attach it to the function:
function.py
--env, --env-file, or
SDK envs=.
NULLSPACE_RUN_ID, NULLSPACE_FUNCTION_ID,
NULLSPACE_VERSION_ID, NULLSPACE_ENVIRONMENT, and NULLSPACE_MACHINE_ID.
Application code can still print or write secrets, so treat logs, output files,
and .env files as sensitive.
Create inline named secrets from Python when a deploy workflow owns secret
material, or prefer pre-created secrets for CI and production:
function.py
State And Sessions
Framework session, thread, checkpoint, or flow state stays app-owned. Store durable state in a mounted volume, a retained or auto-resumed machine, or an external database. For example, keep LangGraph checkpoints in your checkpointer storage, keep Claude session files in a volume if they must survive cleanup, and let CrewAI flows own their state and output artifacts. Do not rely on the ephemeral machine filesystem for durable conversation state unless the machine is retained or the state is written to a mounted volume.Cache And Templates
functions deploy reports function build cache state in human output and JSON.
The default auto policy falls back to running install inside each job run or
service start when no ready artifact exists. Use nullspace functions deploy --rebuild to build a fresh reusable function artifact during upload, or
--no-cache to bypass cache lookup and artifact writes for one deploy. Use a
custom template for heavy system dependencies or slow base setup.
Inside a builder, force_build() / forceBuild() inserts a per-step cache
boundary; template builds can also use whole-build cache bypass with
skip_cache=True, skipCache: true, or nullspace template build --skip-cache.
Examples
Minimal Job
Deploy a small Python job and collect
result.json plus a reports
directory.Minimal Service
Deploy a small Python HTTP service and fetch its public URL.
OpenAI Agents SDK Job
Deploy an OpenAI Agents SDK app as a finite job.
Claude Agent SDK Job
Deploy a Claude Agent SDK app as a finite job.
LangGraph Service
Deploy a LangGraph-backed HTTP service.
CrewAI Job
Deploy a CrewAI project as a bounded job.
Machine + Function Composition
Call a Function from a customer-created machine and inspect retained run
machine state.