Skip to content

Embed Core in an HTTP Service

This tutorial uses the runnable examples/embedded-service project. It shows the minimum shape of a vendor-neutral service: a caller context enters through HTTP, the application selects the tenant, Core runs the agent, and the service returns structured output.

Run

export PRAXO_BASE_URL=http://localhost:11434/v1
export PRAXO_MODEL=llama3.2

cd examples/embedded-service
go run . -addr :8080 -tenant local

Call the service:

curl -s http://localhost:8080/run \
  -H 'Content-Type: application/json' \
  -H 'X-Praxo-Principal: user-1' \
  -d '{"prompt":"What time is it? Use get_time."}'

Python Variant

The Python example uses the same caller-context boundary with the standard library HTTP server:

cd language/python/examples/service
python -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python service.py
curl -s http://127.0.0.1:8080/run \
  -H 'Content-Type: application/json' \
  -H 'X-Praxo-Principal: user-1' \
  -d '{"prompt":"What time is it? Use get_time."}'

Run its deterministic tests with:

.venv/bin/python -m unittest test_service.py -v

Verified Identity Variant

The authenticated service example adds an application-verified HMAC bearer token, subject and tenant claims, expiration checks, a tenant allowlist before the agent runs, and a file-backed checkpoint saved on run completion.

cd examples/embedded-service-auth
go test ./...

This is an application-local token format, not a general JWT implementation. Production services should use their identity provider, key management, audience checks, and revocation.

Python Authenticated Variant

The Python authenticated service example applies the same boundary with the standard library: HMAC bearer tokens, subject and tenant claims, expiration checks, a tenant allowlist, policy binding, and a file-backed checkpoint. Set PRAXO_POLICY_URL to delegate decisions to an application-owned HTTP policy decision service; the example fails closed on timeout, an invalid response, or a denial.

cd language/python/examples/service-auth
python -m venv .venv
.venv/bin/python -m pip install -r requirements.txt

export PRAXO_SERVICE_SECRET=local-development-secret
.venv/bin/python service.py --addr 127.0.0.1:8080

Generate a short-lived token and call the service:

TOKEN=$(.venv/bin/python service.py --print-token user-1 local --ttl 600)
curl -s http://127.0.0.1:8080/run \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"prompt":"What time is it? Use get_time."}'

Run its deterministic tests with:

.venv/bin/python -m unittest test_service.py -v

TypeScript Authenticated Variant

The TypeScript authenticated service example uses Node's standard library with the same HMAC bearer token, tenant allowlist, policy binding, optional external policy decision service, and file checkpoint.

cd language/typescript/examples/service-auth
npm ci

export PRAXO_SERVICE_SECRET=local-development-secret
npm start

Generate a token and call the service:

TOKEN=$(node service.js --print-token user-1 local --ttl 600)
curl -s http://127.0.0.1:8080/run \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"prompt":"What time is it? Use get_time."}'

Run its deterministic tests with:

npm test

Request Flow

  1. The base HTTP handler checks that X-Praxo-Principal is present; the authenticated variants verify a bearer token and derive the principal.
  2. The application selects the tenant and passes both values into the Core session.
  3. The agent calls the model under an explicit timeout.
  4. Policy permits model generation and only the get_time tool.
  5. The handler returns JSON containing the model output.

X-Praxo-Principal is a context stand-in, not authentication. A production service must verify the caller and derive the principal and tenant from trusted application state.

Service Boundary

The base example includes:

  • a /healthz endpoint;
  • POST /run with a bounded JSON body;
  • HTTP read, write, and idle timeouts;
  • a model HTTP timeout;
  • SIGINT/SIGTERM shutdown with a bounded drain;
  • event logging owned by the application.

The base example deliberately does not include durable sessions, checkpoints, approvals, or a tenant store. Those are application or product responsibilities. The authenticated variants add a bounded token check and a file checkpoint.

Test Without a Model

cd examples/embedded-service
go test ./...

The tests use a fake model and httptest, so they do not need an endpoint.

Next Steps

  • Replace the principal header with verified identity.
  • Scope checkpoints, events, and tool access by tenant.
  • Add a durable checkpoint store for long-running work.
  • Put shell, file, and network tools behind application-owned isolation.
  • Use the application integration checklist before production.