AgentStack
SKILL verified MIT Self-run

Policyengine Python Client

skill-policyengine-policyengine-claude-policyengine-python-client-skill · by PolicyEngine

|

No reviews yet
0 installs
6 views
0.0% view→install

Install

$ agentstack add skill-policyengine-policyengine-claude-policyengine-python-client-skill

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Policyengine Python Client? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

PolicyEngine Python Client

> IMPORTANT: Always use the current year (2026) in situation dictionaries and calculate() calls, not 2024 or 2025.

This skill covers programmatic access to PolicyEngine for analysts and researchers.

Installation

If the user asks for the latest PolicyEngine package version, verify from PyPI immediately before installing. Do not rely on search snippets, local installed packages, lockfiles, or old docs as proof of latest.

# Verify the latest umbrella package on PyPI.
python - <<'PY'
import json
import urllib.request

with urllib.request.urlopen(
    "https://pypi.org/pypi/policyengine/json",
    timeout=20,
) as response:
    print(json.load(response)["info"]["version"])
PY
python -m pip index versions policyengine

# Install the Python client, pinned to the verified version.
uv pip install "policyengine==X.Y.Z"

# Or for local development
uv pip install policyengine-us  # Just the US model (offline)

When using policyengine.py as the source of both rules and default microdata, install the country extra at the exact verified umbrella package version:

uv pip install "policyengine[us]==X.Y.Z"
uv pip install "policyengine[uk]==X.Y.Z"

If the user instead asks for the latest direct country package, run the same PyPI JSON + pip index check for policyengine-us, policyengine-uk, or the specific package named by the user, then pin that exact package version.

Confirm the resolved package versions and whether any package is a direct GitHub install:

python - <<'PY'
from importlib import metadata

for package in ["policyengine", "policyengine-us", "policyengine-uk"]:
    try:
        print(f"{package}=={metadata.version(package)}")
        direct_url = metadata.distribution(package).read_text("direct_url.json")
        if direct_url:
            print(f"{package} direct_url={direct_url}")
    except metadata.PackageNotFoundError:
        pass
PY

For bundle/data provenance, inspect the installed release manifest directly instead of relying on a top-level import policyengine; top-level imports can initialize countries you are not using and may require private data tokens.

python - <<'PY'
import json
from importlib import metadata
from pathlib import Path

country = "us"
manifest_path = Path(
    metadata.distribution("policyengine").locate_file(
        f"policyengine/data/release_manifests/{country}.json"
    )
)
manifest = json.loads(manifest_path.read_text())
print(json.dumps({
    "bundle_id": manifest.get("bundle_id"),
    "model_package": manifest.get("model_package"),
    "data_package": manifest.get("data_package"),
    "default_dataset": manifest.get("default_dataset"),
    "default_dataset_uri": (
        manifest.get("certified_data_artifact") or {}
    ).get("uri"),
    "certification": manifest.get("certification"),
}, indent=2, sort_keys=True))
PY

Quick Start: Python Client

from policyengine import Simulation

# Create a household
household = {
    "people": {
        "you": {
            "age": {"2026": 30},
            "employment_income": {"2026": 50000}
        }
    },
    "households": {
        "your household": {
            "members": ["you"],
            "state_name": {"2026": "CA"}
        }
    }
}

# Run simulation
sim = Simulation(situation=household, country_id="us")
income_tax = sim.calculate("income_tax", "2026")

For Users: Why Use Python?

Web app limitations:

  • ✅ Great for exploring policies interactively
  • ❌ Can't analyze many households at once
  • ❌ Can't automate repetitive analyses
  • ❌ Limited customization of charts

Python benefits:

  • ✅ Analyze thousands of households in batch
  • ✅ Automate regular policy analysis
  • ✅ Create custom visualizations
  • ✅ Integrate with other data sources
  • ✅ Reproducible research

For Analysts: Common Workflows

Workflow 1: Calculate Your Own Taxes

from policyengine import Simulation

# Your household (more complex than web app)
household = {
    "people": {
        "you": {
            "age": {"2026": 35},
            "employment_income": {"2026": 75000},
            "qualified_dividend_income": {"2026": 5000},
            "charitable_cash_donations": {"2026": 3000}
        },
        "spouse": {
            "age": {"2026": 33},
            "employment_income": {"2026": 60000}
        },
        "child1": {"age": {"2026": 8}},
        "child2": {"age": {"2026": 5}}
    },
    # ... entities setup (see policyengine-us-skill)
}

sim = Simulation(situation=household, country_id="us")

# Calculate specific values
federal_income_tax = sim.calculate("income_tax", "2026")
state_income_tax = sim.calculate("state_income_tax", "2026")
ctc = sim.calculate("ctc", "2026")
eitc = sim.calculate("eitc", "2026")

print(f"Federal income tax: ${federal_income_tax:,.0f}")
print(f"State income tax: ${state_income_tax:,.0f}")
print(f"Child Tax Credit: ${ctc:,.0f}")
print(f"EITC: ${eitc:,.0f}")

Workflow 2: Analyze a Policy Reform

from policyengine import Simulation

# Define reform (increase CTC to $5,000)
reform = {
    "gov.irs.credits.ctc.amount.base[0].amount": {
        "2026-01-01.2100-12-31": 5000
    }
}

# Compare baseline vs reform
household = create_household()  # Your household definition

sim_baseline = Simulation(situation=household, country_id="us")
sim_reform = Simulation(situation=household, country_id="us", reform=reform)

ctc_baseline = sim_baseline.calculate("ctc", "2026")
ctc_reform = sim_reform.calculate("ctc", "2026")

print(f"CTC baseline: ${ctc_baseline:,.0f}")
print(f"CTC reform: ${ctc_reform:,.0f}")
print(f"Increase: ${ctc_reform - ctc_baseline:,.0f}")

Workflow 3: Batch Analysis

import pandas as pd
from policyengine import Simulation

# Analyze multiple households
households = [
    {"income": 30000, "children": 0},
    {"income": 50000, "children": 2},
    {"income": 100000, "children": 3},
]

results = []
for h in households:
    situation = create_household(income=h["income"], num_children=h["children"])
    sim = Simulation(situation=situation, country_id="us")

    results.append({
        "income": h["income"],
        "children": h["children"],
        "income_tax": sim.calculate("income_tax", "2026"),
        "ctc": sim.calculate("ctc", "2026"),
        "eitc": sim.calculate("eitc", "2026")
    })

df = pd.DataFrame(results)
print(df)

Using the REST API Directly

Authentication

Public access:

  • 100 requests per minute (unauthenticated)
  • No API key needed for basic use

Authenticated access:

  • 1,000 requests per minute
  • Contact hello@policyengine.org for API key

Key Endpoints

Calculate household impact:

import requests

url = "https://api.policyengine.org/us/calculate"
payload = {
    "household": household_dict,
    "policy_id": reform_id  # or None for baseline
}

response = requests.post(url, json=payload)
result = response.json()

Get policy details:

# Get policy metadata
response = requests.get("https://api.policyengine.org/us/policy/12345")
policy = response.json()

Get parameter values:

# Get current parameter value
response = requests.get(
    "https://api.policyengine.org/us/parameter/gov.irs.credits.ctc.amount.base"
)
parameter = response.json()

For Full API Documentation

OpenAPI spec: https://api.policyengine.org/docs

To explore:

# View all endpoints
curl https://api.policyengine.org/docs

# Test calculate endpoint
curl -X POST https://api.policyengine.org/us/calculate \
  -H "Content-Type: application/json" \
  -d '{"household": {...}}'

Limitations and Considerations

Rate Limits

Unauthenticated:

  • 100 requests/minute
  • Good for exploratory analysis

Authenticated:

  • 1,000 requests/minute
  • Required for production use

Data Privacy

  • PolicyEngine does not store household data
  • All calculations happen server-side and are not logged
  • Reform URLs are public (don't include personal info in reforms)

Performance

API calls:

  • Simple household: ~200-500ms
  • Population impact: ~5-30 seconds (varies by reform)
  • Use caching for repeated calculations

Local simulation (policyengine-us):

  • Faster for batch analysis
  • No rate limits
  • No network dependency
  • Limited to one country per package

Choosing Local vs API

Use Local (policyengine-us package)

When:

  • Batch analysis of many households
  • Need offline capability
  • Analyzing parameter sweeps (axes)
  • Development/testing

Install:

uv pip install policyengine-us  # US only
uv pip install policyengine-uk  # UK only

Example:

from policyengine_us import Simulation

# Works offline
sim = Simulation(situation=household)

Use API (policyengine or requests)

When:

  • Multi-country analysis
  • Using latest model version
  • Don't want to manage dependencies
  • Integration with web services

Example:

import requests

# Requires internet
response = requests.post("https://api.policyengine.org/us/calculate", ...)

For Contributors: Understanding the Client

Repository: PolicyEngine/policyengine.py

To see implementation:

# Clone the client
git clone https://github.com/PolicyEngine/policyengine.py

# See the Simulation class
cat policyengine/simulation.py

# See API integration
cat policyengine/api.py

Architecture:

  • Simulation class wraps API calls
  • calculate() method handles caching
  • Transparent fallback between API and local

Advanced: Direct Country Package Usage

For maximum control and performance, use country packages directly:

from policyengine_us import Simulation

# Full control over situation structure
situation = {
    # Complete situation dictionary
    # See policyengine-us-skill for patterns
}

sim = Simulation(situation=situation)
result = sim.calculate("variable_name", 2026)

Benefits:

  • No API dependency
  • Faster (no network)
  • Full access to all variables
  • Use axes for parameter sweeps

See policyengine-us-skill for detailed patterns.

Examples and Tutorials

PolicyEngine documentation:

  • US: https://policyengine.org/us/docs
  • UK: https://policyengine.org/uk/docs

Example notebooks:

  • Repository: PolicyEngine/analysis-notebooks
  • See policyengine-analysis-skill for analysis patterns

Community examples:

  • Blog posts: policyengine.org/us/research
  • GitHub discussions: github.com/PolicyEngine discussions

Getting Help

For usage questions:

  • GitHub Discussions: https://github.com/PolicyEngine/policyengine-us/discussions

For bugs:

  • File issues in appropriate repo (policyengine-us, policyengine.py, etc.)

For collaboration:

  • Email: hello@policyengine.org

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.