Environment Variables#
Pass secrets and runtime knobs to tools running in managed subprocesses.
Why env vars?#
Many tools depend on external services (e.g., OpenAI, Jira, DBs) or need runtime knobs (timeouts, memory hints). Because tools run outside your app (in a subprocess), you pass these settings via environment variables.
How env is constructed (merge order)#
When the SDK launches a tool, it builds the subprocess environment by merging:
- Base/isolated vars (HOME, TMPDIR, etc. set by the SDK)
entrypoint.envfromagent.json(static pairs the tool chooses to include)- Env passed to
load()(per-call)
Later entries win on key conflicts.
- Node:
buildEnv(entrypoint.env, opts.env, HOME, TMPDIR) - Python:
_build_env(entrypoint.env, env, HOME, TMPDIR)
If a tool declares required environment variables without a default, the SDK load() function will fail immediately when that variable is missing. Provide the value by passing it per-call via load().
The SDK does not read your app’s process env for tool variables. Only entrypoint.env and the env you pass to load() are merged into the subprocess.
Set env vars per call (SDK)#
Node#
import { load } from '@agentpm/sdk';
const summarize = await load('@zack/summarize@0.1.3', {
env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
timeoutMs: 30_000,
});
const out = await summarize({ text: '...' });Python#
from agentpm import load
import os
summarize = load(
"@zack/summarize@0.1.3",
env={ "OPENAI_API_KEY": os.environ["OPENAI_API_KEY"] },
timeout=30.0,
)
out = summarize({ "text": "..." })Runtime knobs you can control via env#
These variables are SDK-level knobs, not tool inputs. They’re read from the host process environment (before the subprocess is spawned), so do not pass them via load(... env=...). Set them on the running process instead.
- In Node, the SDK reads them from
process.env. - In Python, the SDK reads them from
os.getenv(...).
Examples:
# macOS/Linux
export AGENTPM_DEBUG=1
export AGENTPM_NODE=/usr/local/bin/node
export AGENTPM_TOOL_DIR=/opt/tools# Windows (PowerShell)
$env:AGENTPM_DEBUG = "1"
$env:AGENTPM_PYTHON = "C:\Python311\python.exe"
$env:AGENTPM_TOOL_DIR = "D:\agentpm\tools"-
General (both SDKs)
AGENTPM_TOOL_DIR— Override where tools are discovered (highest priority). Useful for local testing or custom layouts.AGENTPM_DEBUG=1— Verbose SDK logging (prints resolution, PATH checks, spawn args).AGENTPM_NODE / AGENTPM_PYTHON— Interpreter override. If the manifest’sentrypoint.commandimplies Node or Python, these let you force the exact binary, e.g.:- macOS/Linux:
export AGENTPM_NODE=/usr/local/bin/nodeexport AGENTPM_PYTHON=/usr/local/bin/python3.11
- Windows (PowerShell):
$env:AGENTPM_NODE="C:\Program Files\nodejs\node.exe"$env:AGENTPM_PYTHON="C:\Python311\python.exe"
- macOS/Linux:
-
Node tools
AGENTPM_NODE_OLD_SPACE_MB— Sets--max-old-space-size(default:256). Increase for memory-intensive tools.AGENTPM_NODE_JITLESS=1— Add--jitlessautomatically (or include the flag inentrypoint.args).
-
Python tools
- SDK injects
-I -Bautomatically (isolated mode, no.pyc). No env needed. AGENTPM_RLIMIT_AS_MB— Optional address-space cap applied by the Python SDK’s POSIX rlimits helper (disabled on macOS and when running Node tools). Set to a positive integer MB to enable (e.g.,2048).
- SDK injects
entrypoint.env < env passed to load(). Later sources override earlier ones.
Best practices#
- Keep secrets out of the repo. Don’t hardcode keys in
agent.json. Load from your secret manager/CI and pass via env. - Document expectations. In your tool README/description, list required env vars and accepted values.
- Validate early. If a key is missing, fail fast with a clear error to stderr.
- Prefer scoped keys. Names like
MYTOOL_API_KEYreduce collisions across tools. - Combine with timeouts. Pair env-based knobs with timeoutMs/timeout so misconfigurations don’t hang runs.
Troubleshooting#
- Interpreter not picking up env? Log
process.env.KEY(Node) oros.getenv("KEY")(Python) inside the tool—to stderr—to confirm visibility. - Conflicting values. Remember later sources override earlier ones. If a value isn’t taking effect, check if your process env is overriding it.
- OOM/slow runs (Node). Raise
AGENTPM_NODE_OLD_SPACE_MBor add your own--max-old-space-size=....ConsiderAGENTPM_NODE_JITLESS=1only if you know you need it. - Too much output (Python SDK). Combined stdout+stderr > 10MB will fail the run. Keep logs concise; reserve stdout for the single JSON result.