Offline / air-gapped install¶
kneo-agent is a pure-Python library that does not phone home and
does not require network access at runtime — beyond whatever your
own application chooses to talk to. This page explains how to
install it on a host with no outbound internet, and what that means
for your audit story.
No phone-home guarantee¶
The SDK does not perform analytics, telemetry, update checks, or "call home" requests of any kind. The only outbound network calls the SDK can make are:
- Provider SDK calls through the optional extras
(
openai-agents,langchain,google-adk). These only trigger when your code invokes an agent that uses those extras, and they go to the endpoints your code configured (e.g.base_url=...for a local Ollama). - MCP HTTP / SSE transports (
MCPServerConfig.http()/.sse()). These only trigger when your code registers an MCP server.
The [telemetry] extra ships only opentelemetry-api, which has
no exporter — your deployment chooses where to ship spans (none,
a local OTLP collector, etc.). See
self_hosted_observability.md.
For a code-level audit, grep for outbound calls in
kneo_agent/ — you will find urllib.request.urlopen only inside
kneo_agent/mcp/client.py (the MCP transports) and nothing else.
Installing in an air-gapped environment¶
The standard pattern: download wheels on a connected host, transfer
them to the air-gapped host, install with --no-index --find-links.
1. On a connected host¶
# Choose the same Python version + platform as the target host.
# --platform / --python-version match what `pip install` would
# resolve on the target.
mkdir -p wheelhouse
pip download \
--dest wheelhouse \
--python-version 3.12 \
--platform manylinux2014_x86_64 \
--only-binary=:all: \
"kneo-agent[all]==1.2.0"
Adjust --platform for your target (e.g.
manylinux_2_28_x86_64, macosx_14_0_arm64). Drop [all] to
omit provider extras you don't need; the matching set keeps only
core + PyYAML.
2. Transfer the wheelhouse¶
rsync, scp, USB, whatever your security model requires. The
wheelhouse is just a directory of .whl and .tar.gz files —
nothing in it executes during transfer.
3. On the air-gapped host¶
python -m venv /opt/myapp/venv
source /opt/myapp/venv/bin/activate
pip install --no-index --find-links /path/to/wheelhouse \
"kneo-agent[all]==1.2.0"
--no-index tells pip not to consult any package index;
--find-links points it at the local directory. If the resolver
complains about a missing dependency, your pip download step on
the connected host missed it — re-run pip download with the same
flags as your target install, or add the missing package name
explicitly.
4. Verify¶
For the no-phone-home guarantee, smoke-test on a host with no outbound network at all:
# Block all egress (example with iptables; adjust for your platform).
sudo iptables -A OUTPUT -j REJECT
python -c "
from kneo_agent import AgentBuilder
agent = AgentBuilder().with_name('air-gap').build()
print(agent)
"
Importing the SDK and constructing an Agent (without invoking a
provider) makes zero outbound calls.
Reproducible installs¶
For audit-grade reproducibility:
pip download --dest wheelhouse \
--no-deps \
"kneo-agent==1.2.0"
pip download --dest wheelhouse "kneo-agent==1.2.0" # then resolve deps
sha256sum wheelhouse/* > wheelhouse.SHA256SUMS
Verify on the target host:
If your release pipeline already produces a manifest, use that as
the source of truth — kneo-agent has nothing kneo-specific to add
beyond standard pip-wheel discipline.
Updating in place¶
Because the SDK does not check for updates, upgrading is entirely
your call. Re-run the pip download step on a connected host
against the new version, transfer, and re-install with
--no-index --find-links against the new wheelhouse.
The upgrading_to_1.2.md guide
covers the user-facing changes between minor releases.
What you still need network access to (just not from the SDK itself)¶
- Whatever LLM provider your agent talks to (a local Ollama / vLLM / llama.cpp server is fine; that's still on-prem).
- Whatever MCP servers your agent uses (
MCPServerConfigcan point at alocalhostURL — no public network needed). - Whatever observability backend your application ships spans to
(a local OTLP collector / Jaeger / Tempo / SigNoz — see
self_hosted_observability.md).
The library installs and runs without any of those. They become required only when your application code chooses to use them.