Actspan Docs Quickstart
DocsExamples

Demonstrate allowed runs, gateway denials, and saved local policy blocks with fixed responses.

On this page

Run Actspan through a LiteLLM gateway

Demonstrate an allowed agent, a gateway permission denial, and an Actspan policy block before model execution. Inspect the saved outcomes, change the local policy, and restore it to let the agent run again.

LiteLLM runs as a real service with PostgreSQL-backed virtual keys. Its model responses are fixed fixtures: no OpenAI key or paid model request is needed. This is a compatibility demonstration, not a gateway policy connector.

For customer service, research and summarization, and planning with actual model responses, follow the separate live workflow demos.

Before you begin

Use the separately supplied gateway fixture. Complete its matching-file and service prerequisites below before running the requests.

Problem and flow

An engineering team already has an OpenAI-compatible agent, but model access must pass through LiteLLM's virtual keys. The team needs to distinguish a request stopped by local Actspan admission from one sent to the gateway and rejected there, while retaining the attempted configuration and execution result.

Two independent gates before an answer

What this proves

The supplied checker pairs an allowed fixed-response workflow with a typed gateway model-access denial and the CLI's saved permission failure. A separate manual policy edit demonstrates a local block before dispatch; restoration demonstrates the allowed path again. The reports identify the local configuration revision and individual outcomes. They do not prove live model quality, remote configuration identity, shared budgets or signed gateway audit delivery. See the qualification card below for the method and current scope.

Qualification and availability

Item Scope
Availability Separately supplied design-partner gateway package; absent from public2.
Method Source-checked instructions; no current exact-artifact container/live acceptance record is published on this page.
Runtime Recipe targets CLI 0.2.0; gateway image/config/example hashes must come from the matching handoff.
Current proof Use the provider matrix for recorded trials. Native direct-provider results do not qualify this gateway route.
Acceptance Inspect the named tool, handoff/checkpoint and saved records below; stop on missing prerequisites or unexpected status.

Start here

This optional demo needs a separate complete gateway-demo handoff. Ask your Actspan contact for this design-partner handoff; its scripts and Compose files are not part of the public native examples archive or the free CLI download. The source repository stays private and no clone command is required. Once supplied, you need the Actspan 0.2.0 CLI on your PATH, the example files, Python 3, and a running Docker installation with Docker Compose. The helper uses Python's standard library and calls the installed CLI; it does not require Actspan to be installed in that Python environment. The first startup downloads the container images.

Follow the numbered steps in one terminal. Copy only the commands, without the terminal prompt or example output. Enter the supplied demo directory:

cd /path/to/actspan-gateway-demo/examples_latest/gateways/litellm
command -v actspan

If actspan is not found, activate the environment containing your existing CLI or follow the installation guide before continuing.

1. Start the gateway and validate

python3 demo.py up
actspan validate workspace.yaml --strict-env

Expected: LiteLLM is ready at http://127.0.0.1:4008 and validation reports OK. The helper starts the demo's LiteLLM and PostgreSQL services, creates disposable credentials, and prepares local environment settings used by Actspan. .env supplies the gateway endpoint and restricted key; .actspan.env disables portal reporting and response caching. Both files have private permissions. Run the commands in this directory so Actspan loads that configuration.

Use a clean copy of the example if setup finds an existing environment file. The helper preserves existing files and refuses to overwrite generated files that you have edited. Shell variables take precedence over environment files for manual commands; use a clean shell if you previously exported different gateway, portal, or cache settings. demo.py check explicitly sets the demo's endpoint, restricted key, local reporting, and disabled caching for its CLI subprocesses.

Validation checks configuration and required environment values. It does not prove that a gateway credential is authorized; the following requests exercise that boundary.

The gateway advertises two models, gpt-4.1-mini and gpt-4.1. Both are permitted by the example's Actspan policy. The demo virtual key permits only gpt-4.1-mini, making the gateway responsible for rejecting the second model. The names identify mock routes; this example does not measure either model.

Run the commands yourself

2. Run and inspect the allowed agent

actspan run workspace.yaml summarize_agent \
  --input-text 'Topic: Example Robotics' \
  --admission=block --format text
actspan inspect summarize_agent

Expected: Status: succeeded, the Example Robotics summary, and saved token and cost metrics. The supplied fixture has shown 123 tokens and $0.000960; these are synthetic usage and a cost calculated from example prices, not billed model usage. For the same run ID, runs and inspect should show the same cost.

3. Demonstrate the gateway restriction

Try the model that the virtual key cannot access:

actspan run workspace.yaml restricted_agent \
  --input-text 'Topic: Example Robotics' \
  --format text
actspan inspect restricted_agent

Expected: PROVIDER_PERMISSION_DENIED, HTTP 403, and a saved failed run for restricted_agent. The reason says the key cannot access gpt-4.1. The command intentionally exits nonzero; continue with inspection and the next step.

Both models pass the original local policy. This request reaches LiteLLM, which rejects it using the key's permissions. The OpenAI adapter may label the message OpenAI permission denied (403); the destination is the configured LiteLLM endpoint. Changing an Actspan YAML file does not change the gateway's permissions.

Demonstrate a local policy block

4. Back up and change only the Actspan policy

Keep the gateway running and use the same terminal until the policy is restored. The backup path is held in policy_demo_backup. This changes only the local allowlist; the agent and gateway key still use the same configuration.

policy_demo_backup=$(mktemp)
cp policies.yaml "$policy_demo_backup"
python3 - <<'PY'
from pathlib import Path

path = Path("policies.yaml")
original = path.read_text()
allowed = "openai: [gpt-4.1-mini, gpt-4.1]"
if original.count(allowed) != 1:
    raise SystemExit("Expected the original demo allowlist; policy was not changed.")
path.write_text(original.replace(allowed, "openai: [gpt-4.1]", 1))
print("Local policy now permits only gpt-4.1.")
PY

Expected: the policy now permits only gpt-4.1. The previously allowed summarize_agent still requests gpt-4.1-mini.

5. Run again and inspect the saved block

actspan run workspace.yaml summarize_agent \
  --input-text 'Topic: Example Robotics' \
  --admission=block --format text
actspan inspect summarize_agent
actspan runs --limit 10

Expected: the run exits with code 5 and ADMISSION_BLOCKED. This is the successful demonstration of a policy block. Inspection includes these fields:

Agent: summarize_agent
Status: blocked
Error: ADMISSION_BLOCKED
Reason: Admission blocked: POLICY_DENY::ALLOWLIST::ALLOWLIST::MODEL_NOT_ALLOWED (openai:gpt-4.1-mini)
Executed: false
Enforcement source: actspan_admission
Model: gpt-4.1-mini
Admission mode: block
Policy: gateway_compatibility@1.0.0

It also shows the attempt's own run ID and configuration revision, plus the Git source revision when available. Keep the exact actspan inspect command printed by the blocked run to revisit this decision later. Inspection by agent name selects the latest saved attempt, which changes after you run the agent again.

Run history should contain one row per run ID, including the allowed run, gateway failure, and local block. The listing uses success and error for agent records; inspection presents those as succeeded and failed. A local block stays blocked.

6. Restore the policy and run again

cp "$policy_demo_backup" policies.yaml
rm "$policy_demo_backup"
unset policy_demo_backup
actspan run workspace.yaml summarize_agent \
  --input-text 'Topic: Example Robotics' \
  --admission=block --format text
actspan inspect summarize_agent

Expected: the agent succeeds again. The historical blocked record remains saved under its own run ID. Restore the policy even if you stop the walkthrough early; demo.py down does not restore edited policy files.

Read the saved decision

Field What it means for the local block
Status: blocked and Executed: false Actspan stopped this request before model execution.
MODEL_NOT_ALLOWED The requested model was outside the local allowlist.
Enforcement source: actspan_admission Actspan made this decision before dispatching the model request to LiteLLM.
Policy name and version Identify the selected policy. Editing its contents does not automatically increment its version label.
Configuration revision Fingerprints the local configuration for this attempt, including the policy files and referenced LiteLLM config file. Editing either changes this fingerprint.
Source revision The Git commit when available. Uncommitted policy edits can change the configuration revision without changing this commit.
Latency Time processing the admission attempt; a value such as 0.5s is not model generation time.
Cost and tokens: - No model cost or usage is recorded for the local block. A dash means unavailable, not measured zero.

For a live presentation: Actspan checks the agent against its policy before execution and saves the decision, reason, and configuration revision as evidence. LiteLLM separately enforces permissions on requests that reach the gateway.

The local evidence reference explains saved outcomes and revisions. The walkthrough assumes local state is enabled; using --no-state skips persistence, so the run cannot be inspected afterward.

What the check demonstrates

7. Run the workflow, evaluation, and automated checks

After restoring the policy:

actspan run workspace.yaml company_summary \
  --input-text 'Topic: Example Robotics' --format text
actspan inspect company_summary
actspan eval run eval_summary.yaml \
  --fail-on-constraints \
  --report-json .actspan/gateway-demo/eval.json
python3 demo.py check
actspan runs --limit 10

Expected: the workflow succeeds, the fixture evaluation passes, and all seven automated checks report PASSED:

Check Expected result
workspace_validation Workspace and required environment values validate.
configuration_revision_recorded The native local configuration revision is recorded.
allowed_workflow company_summary returns the fixed summary.
gateway_model_permission A separate direct request receives LiteLLM's typed model-access 403.
denial_reaches_cli The restricted agent returns a permission failure through Actspan.
fixture_evaluation_and_revision Output checks and constraints pass for the recorded revision.
configuration_unchanged The configuration is unchanged across the automated check.

These seven checks cover the original gateway configuration. The local policy edit, block, and restore in steps 4–6 are a separate manual demonstration. Run check only after restoration so both models pass local admission.

The helper invokes the real CLI and writes .actspan/gateway-demo/report.json, with evaluation details in eval.json and command output alongside them. It separates the expected denied request from the allowed run. Helper exit codes are 0 for passed, 1 for a failed expectation, and 2 for an inconclusive result or setup failure. A timeout or invalid key does not prove model restrictions.

The checked setup uses LiteLLM 1.102.0, PostgreSQL 17-alpine, and mock Responses API output. Fixture evaluations assess output structure and configured checks; they do not measure model accuracy, factual correctness, or actual charges.

Understand the boundary

The workspace keeps the LiteLLM connection separate from its OpenAI adapter:

gateways:
  litellm:
    type: litellm
    config_file: ./litellm_config.yaml
    base_url: ${LITELLM_BASE_URL}
    secrets:
      api_key: ${LITELLM_API_KEY}

providers:
  primary:
    type: openai
    gateway: litellm

primary is the provider alias used by this demo's actions; litellm is the named gateway connection. The adapter uses the demo virtual key and gateway endpoint. A missing gateway setting does not fall back to direct OpenAI. config_file links the workspace to the native LiteLLM file used by the mock Compose stack. It is relative to workspace.yaml. Actspan checks the local file's basic structure and fingerprints its contents; Compose mounts it into LiteLLM. Actspan does not apply the file to the running gateway. The request uses the Responses API. This example does not establish compatibility with gateways that expose only Chat Completions or with every provider operation, streaming mode, or tool integration.

The helper obtains the native configuration revision using actspan verify and retains its complete output in .actspan/gateway-demo/revision.stdout. That command can report unsupported checks. Recording a revision does not mean that all native controls passed or that every declared policy is enforced.

Actspan configuration fingerprints include the local file referenced by config_file, but exclude resolved environment values and the gateway's effective configuration. The demo also records a separate hash of its configuration files for reproducibility. Neither hash establishes that the running gateway loaded that file or detects remote configuration drift. The report does not synchronize policy, correlate gateway audit receipts, enforce an organization-wide budget, or demonstrate remote MCP authorization.

The gateways block configures connections; it does not install or upgrade LiteLLM or provide an admin API integration. Optional provider plugin_version selects the Actspan adapter package, not the gateway server. See provider and gateway configuration.

This handoff targets Actspan 0.2.0 and pins LiteLLM 1.102.0 in compose.yaml. The default demo uses an available OpenAI adapter; init records its actual version. The independent adapter for this handoff is 0.1.1, selected with an optional plugin_version if that package is available from your index. See credentials and versions for the CLI/adapter constraints and the OPENAI_API_KEY export required by live mode. This mock walkthrough needs only its generated LITELLM_API_KEY.

The next integration step would be to inspect a gateway's effective settings and compare them with explicit contract requirements. That capability is outside this example.

Stop the demo

8. Clean up after the policy is restored

python3 demo.py down

The helper removes the demo's services, disposable database resources, and unchanged generated environment files. Modified environment files and evidence reports are preserved. Cleanup is scoped to this demo rather than other Docker projects.

Source and references