Telemetry and outbound connections
What a self-hosted Future AGI install sends to Future AGI and to other hosts, what it never sends, and how to turn deployment telemetry off or block it.
In this page
A self-hosted install makes one kind of call home on its own: deployment telemetry to Future AGI, on by default. An install with an Enterprise licence makes a second: licence activation and a licence heartbeat, which carries the same instance id and usage counts. This page covers what it sends and when, what it never sends, how to turn it off, how to see what your install sent, and every other outbound connection the platform and the browser UI make. It applies to Standalone, Distributed and Helm. The exact payloads are under Registration and Heartbeat.
After the first account is created, the install registers once with api.futureagi.com, including the email addresses of its owner, admin, staff and superuser accounts, then sends usage counts every 6 hours. It never sends traces, prompts, outputs, datasets or keys. Turn it off with ./bin/install --no-telemetry or FUTURE_AGI_TELEMETRY_DISABLED=true; one minimal registration without email addresses still goes out, so block api.futureagi.com to send nothing. The only other connections made by default are litellm’s price-list download, the model server’s downloads from the Hugging Face Hub, and the assets users’ browsers load from public hosts. An Enterprise licence adds its own heartbeat. Every other outside service stays off until you give it a key.
At a glance
| Connection | On by default? | Destination | Controlled by |
|---|---|---|---|
| Deployment telemetry | Yes | FUTURE_AGI_TELEMETRY_URL (default https://api.futureagi.com) | FUTURE_AGI_TELEMETRY_DISABLED=true turns it off |
| HubSpot lead sync | No | api.hubapi.com | HUBSPOT_API_TOKEN |
| Slack “new user” message | No | Your webhook | SLACK_WEBHOOK_CHANNEL |
| Slack internal alerts | No | Your webhook | ERROR_LOGS_WEBHOOK |
| Mixpanel (server) | No | api.mixpanel.com | MIX_PANEL_TOKEN |
| PostHog (server) | No | POSTHOG_HOST | POSTHOG_API_KEY |
| reCAPTCHA | No | www.google.com/recaptcha | RECAPTCHA_SECRET_KEY, RECAPTCHA_ENABLED |
| Sentry | No | Your DSN | SENTRY_DSN |
| No (printed to the app log) | Mailgun | MAILGUN_API_KEY | |
| Enterprise licence check | Only with a licence | FUTURE_AGI_LICENSE_URL | EE_LICENSE_KEY |
| Google Tag Manager (UI page) | No | www.googletagmanager.com | VITE_GTM_ID at frontend build time |
| Browser UI: fonts and icons | Yes, from each user’s browser, on every page | fonts.googleapis.com, fonts.gstatic.com, api.iconify.design | Not switchable; see The browser UI |
| Browser UI: editor, previews, videos, logos | Yes, from the browser, on the screens that use them | cdn.jsdelivr.net, unpkg.com, view.officeapps.live.com, Loom, Arcade, flagcdn.com, an S3 bucket, flaticon.com | Not switchable; see The browser UI |
| Browser analytics, error reports, ad pixels | No | Mixpanel, PostHog, Sentry, New Relic, Google, Reddit, X | VITE_* keys at frontend build time; see The browser UI |
| Model price list (litellm) | Yes, at each API and worker start | raw.githubusercontent.com | LITELLM_LOCAL_MODEL_COST_MAP=True in .env uses the list bundled with the image (prices as of the pinned litellm release) |
Model downloads (serving) | When serving runs, the first time each model loads | The Hugging Face Hub | Pre-seed the model cache, then HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 |
| Public-IP lookup (installer only) | No | ifconfig.io, then api.ipify.org | ./bin/install makes it only when VITE_HOST_API names a host other than localhost |
Model providers, SSO providers and integrations you add in the product are called only when you configure them and use them. Other outbound connections has the details, the installer included.
What is sent
Future AGI uses deployment telemetry to count the installs that are running, which versions they run, and roughly how much they are used. It never includes anything you send through the product.
Registration, once per install. The app tries to register right after the first account is created, whether through the sign-up page or python manage.py create_user, which ./bin/install runs. It runs on a background thread, so the sign-up page returns without waiting for it. create_user waits for it before exiting, which takes a few seconds, longer if the telemetry URL does not answer: three tries, each bounded by FUTURE_AGI_TELEMETRY_TIMEOUT_SECONDS, which ./bin/install sets to 2 for that command unless you set it. If that attempt fails, the scheduled job below retries it. Registration is sent again only if you turn telemetry off or back on, or if the install loses the signing secret it received the first time.
Heartbeats, every FUTURE_AGI_TELEMETRY_INTERVAL_HOURS (6 by default), started by a recurring Temporal schedule with up to FUTURE_AGI_TELEMETRY_JITTER_SECONDS (30 minutes by default) of random delay. Each heartbeat covers the previous fixed UTC window, for example 06:00 to 12:00, and holds counts only, across the whole install.
Nothing is sent at startup or on login.
Registration
A registration payload, and what each field means:
{
"schema_version": 1,
"instance_id": "5b0c6a4e-8f0e-4c55-9d1a-2f5c1a7e9b3d",
"version": "1.8.0",
"deployment_type": "docker",
"timestamp": "2026-09-25T10:15:00Z",
"telemetry_disabled": false,
"users": [
{
"email": "owner@example.com",
"domain": "example.com"
}
]
}
| Field | Meaning |
|---|---|
schema_version | Version of this payload format. |
instance_id | A random UUID created on first run and stored in your database. It identifies the install, not a person. |
version | The first of FUTURE_AGI_VERSION, SERVICE_VERSION and GIT_SHA that names a release (unknown and latest are skipped), else unknown. FUTURE_AGI_VERSION is the image tag in .env; SERVICE_VERSION and GIT_SHA come from the image. |
deployment_type | FUTURE_AGI_DEPLOYMENT_TYPE if set (docker in both compose files); otherwise kubernetes, docker or bare_metal, detected. |
timestamp | When the payload was built (UTC). |
telemetry_disabled | false here. true on the opt-out registration. |
users | One entry for each active account that is an organization owner or admin, or a Django staff or superuser account (for example one made with manage.py createsuperuser), at the time of registration, most recent login first, at most 500. On a new install that is normally only the first account. |
users[].email | The account’s email address, lowercased. |
users[].domain | The part of email after the @. |
Heartbeat
A heartbeat payload, what its fields mean and what each count covers:
{
"schema_version": 1,
"instance_id": "5b0c6a4e-8f0e-4c55-9d1a-2f5c1a7e9b3d",
"version": "1.8.0",
"window_start": "2026-09-25T06:00:00Z",
"window_end": "2026-09-25T12:00:00Z",
"active_users_count": 3,
"traces_count": 1520,
"spans_count": 20417,
"projects_count": 1,
"eval_logger_count": 212,
"model_hub_evaluations_count": 40,
"dataset_eval_runs_count": 96,
"total_evaluations_count": 348,
"simulation_runs_count": 2,
"simulation_calls_count": 18,
"experiments_count": 1,
"gateway_requests_count": 930,
"datasets_count": 2
}
| Field | Meaning |
|---|---|
schema_version | Same as in registration. |
instance_id | Same as in registration. |
version | Same as in registration. |
window_start | Start of the fixed UTC window the counts cover, included. A heartbeat covers the previous window, for example 06:00 to 12:00. |
window_end | End of that window, excluded. |
Every count covers only that window, across the whole install:
| Field | Counts |
|---|---|
active_users_count | Distinct users who created a project, dataset, evaluation or experiment, plus owners of projects that received spans. |
traces_count | Distinct traces received. |
spans_count | Spans received. |
projects_count | Projects created. |
eval_logger_count | Evaluation results logged on traces. |
model_hub_evaluations_count | Evaluations created. |
dataset_eval_runs_count | Evaluation cells written in datasets. |
total_evaluations_count | The sum of the three evaluation counts above. |
simulation_runs_count | Simulation runs started. |
simulation_calls_count | Calls those simulation runs completed. |
experiments_count | Experiments created. |
gateway_requests_count | Requests through the Agent Command Center gateway. |
datasets_count | Datasets created. |
A count is null when it could not be read (for example, ClickHouse was
unavailable), so a failure is never reported as zero.
How it is sent
- Each payload is an HTTPS
POSTof JSON toFUTURE_AGI_TELEMETRY_URL(https://api.futureagi.comby default) plus/telemetry/register/or/telemetry/heartbeat/, with aFUTURE_AGI_TELEMETRY_TIMEOUT_SECONDStimeout (5 by default), tried up to 3 times. A payload over 512 KiB is not sent. - The registration response carries a per-install secret. Heartbeats are signed with it (HMAC-SHA256, in the
X-FAGI-Telemetry-Signatureheader), so the receiver can reject forged ones. - A heartbeat that cannot be delivered is kept as a JSON file in
FUTURE_AGI_TELEMETRY_BUFFER_DIR, a directory only the app’s user can read, and sent on a later run, oldest first. Files older than 30 days are deleted. - Telemetry failures are logged as warnings and never stop the app, a sign-up or a login.
The receiving server sees the IP address the request comes from, as any HTTPS server does; the payload does not contain it. On Future AGI’s side, the receiving service stores registrations and heartbeats and can pass registrations on to Future AGI’s own CRM, product-analytics and team-chat tools.
What is never sent
Prompts, model outputs, trace or span contents and attributes, dataset rows, evaluation inputs or results, API keys, provider keys, passwords, names, organization or project names, and the email addresses of members who are not owners, admins, staff or superusers.
Turn it off
-
At install:
./bin/install --no-telemetry(Windows:.\bin\install.ps1 -NoTelemetry) writesFUTURE_AGI_TELEMETRY_DISABLED=trueto.envbefore anything starts, so even the first account’s registration is the minimal one. The installer prints what telemetry sends before it asks for the first account’s email. -
Standalone or Distributed, after install: uncomment or add
FUTURE_AGI_TELEMETRY_DISABLED=truein.env(1,yesandonalso work), then recreate the containers. Both compose files pass the variable to every backend process.docker compose up -d -
Helm:
config.telemetry=falsein your values sets the variable for the backend, the workers and the bootstrap job.global.airgap=trueturns telemetry off too, along with the licence heartbeat (unlesslicense.heartbeatistrue), the price-list download and model serving’s downloads. Offline, the one opt-out registration below then fails the same harmless way and is retried. See Configure.
With telemetry off, no email addresses and no heartbeats are sent, and buffered heartbeats are deleted. One opt-out registration is still sent, so Future AGI can count installs that opted out. It contains only schema_version, instance_id, version, deployment_type, timestamp and telemetry_disabled: true, and is sent again only if you turn telemetry back on and off. Until one gets through, it is attempted at every telemetry run.
To make no connection to Future AGI at all, also block outbound traffic to api.futureagi.com (or the host in your FUTURE_AGI_TELEMETRY_URL) at your network. The failed attempts are logged as warnings and change nothing else.
Settings
Every setting of deployment telemetry, with its default in each setup (S Standalone, D Distributed, H Helm), as in the Configuration reference:
| Key | Default | Setups | What it does |
|---|---|---|---|
FUTURE_AGI_TELEMETRY_DISABLED | false | S D H | true opts out (1, yes and on also work): no email addresses and no heartbeats are sent, and buffered heartbeats are deleted; one minimal registration remains (what it contains). ./bin/install --no-telemetry (.\bin\install.ps1 -NoTelemetry) writes it before anything starts. Helm: config.telemetry=false. |
FUTURE_AGI_TELEMETRY_URL | https://api.futureagi.com | S D H | Where registrations and heartbeats go. Change it only to test against another receiver. |
FUTURE_AGI_TELEMETRY_INTERVAL_HOURS | 6 | S D H | Heartbeat interval: 1, 2, 3, 4, 6, 8, 12 or 24. Other values fall back to 6. |
FUTURE_AGI_TELEMETRY_JITTER_SECONDS | 1800 | S D H | Maximum random delay added to each scheduled run, so installs do not all send at once. |
FUTURE_AGI_TELEMETRY_TIMEOUT_SECONDS | 5 | S D H | Timeout of each request. ./bin/install runs its create_user with 2 unless this is set, so an unreachable telemetry URL delays the first account only briefly. |
FUTURE_AGI_TELEMETRY_BUFFER_DIR | S: /data/telemetry; D: /tmp/futureagi-deployment-telemetry; H: futureagi-deployment-telemetry under the system temp dir | S D H | Where undelivered heartbeats wait for the next attempt, in a directory only the app’s user can read. Files older than 30 days are deleted. |
FUTURE_AGI_DEPLOYMENT_TYPE | S D: docker; H: detected: kubernetes | S D H | Reported as deployment_type in telemetry. Unset, it is detected: kubernetes, docker or bare_metal. |
Telemetry reports FUTURE_AGI_VERSION, the image tag, as version: see the version field under Registration.
See what your install sent
-
On the first telemetry run, each process logs one
deployment_telemetry_disclosureline saying what it sends, where, and how to turn it off. -
The last registration payload is kept in your own database. This works for Standalone and Distributed alike:
docker compose exec postgres sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -x -c \ "SELECT instance_id, registration_kind, registered_at, registration_metadata, last_heartbeat_at FROM deployment_telemetry_state"' -
Heartbeats waiting to be delivered are plain JSON files in
FUTURE_AGI_TELEMETRY_BUFFER_DIR:/data/telemetryin Standalone,/tmp/futureagi-deployment-telemetryin Distributed.
Third-party services
Each of these stays off until you set its key, and none is needed to run Future AGI. With no key set, the app makes no request to that service, logs nothing about it above debug level, and never slows down or fails a sign-up or login because of it.
| Service | Turned on by | What it does |
|---|---|---|
| HubSpot | HUBSPOT_API_TOKEN | Lead sync for Future AGI Cloud. Email and SSO sign-ups, and a user without an organization creating one, create or update a HubSpot contact, except while ENV_TYPE is local, the Compose default. Each login marks the contact as logged in, in the background, so HubSpot never delays or fails a login. Accounts created with a password chosen up front, as on the open-source sign-up page or with manage.py create_user, never create a contact, key or not. Without the key: no HubSpot request, no background thread, no log line above debug. |
| Slack | SLACK_WEBHOOK_CHANNEL, ERROR_LOGS_WEBHOOK | SLACK_WEBHOOK_CHANNEL posts a “new user joined” message after an email or SSO sign-up, except while ENV_TYPE is local. ERROR_LOGS_WEBHOOK posts internal alerts, for example a failed HubSpot update or an unavailable embeddings service, never while ENV_TYPE is local or test. |
| Mixpanel | MIX_PANEL_TOKEN | Server-side product analytics events (sign-up, login, SDK use). Each request has a 5-second timeout and is not retried, and a Mixpanel failure never fails a sign-up or login. |
| PostHog | POSTHOG_API_KEY, and POSTHOG_HOST (default https://us.i.posthog.com) | Server-side product analytics events for API requests |
| reCAPTCHA | RECAPTCHA_ENABLED, RECAPTCHA_SECRET_KEY | Checks sign-up, login and token refresh. See below. |
| Sentry | SENTRY_DSN, plus SENTRY_ENABLED=true while ENV_TYPE is local | Sends error reports to your Sentry project. SENTRY_ENABLED=false turns them off even with a DSN. |
| Mailgun | MAILGUN_API_KEY | Sends invites and password resets. Without it, emails are written to the app log. |
reCAPTCHA. Off on a self-hosted install: the compose files set RECAPTCHA_ENABLED=false, while Future AGI Cloud checks sign-up, login and token refresh by default. To turn it on, set RECAPTCHA_SECRET_KEY and RECAPTCHA_ENABLED=true on the backend, and build the frontend with VITE_GOOGLE_SITE_KEY: the published frontend image has none, so leave it off with the published images. On Helm, config.recaptcha=true sets RECAPTCHA_ENABLED, and the chart refuses to render it without RECAPTCHA_SECRET_KEY (in secrets.extra or config.extraEnv) or a config.extraEnvFrom source. When RECAPTCHA_ENABLED is unset, outside Compose, the check runs only if RECAPTCHA_SECRET_KEY is set and ENV_TYPE is not local or development. RECAPTCHA_ENABLED=true without a secret is a misconfiguration: the check can never pass, so sign-ins that go through it are rejected.
The published UI images are built without browser analytics keys, so users’ browsers send nothing to Mixpanel, PostHog, Sentry, Google Tag Manager or ad networks: see The browser UI. USAGE_EVENTS_ENABLED stays false in both compose files and in the chart (config.usageEvents): only Future AGI Cloud drains that Redis stream, and turned on anywhere else it grows until it takes the memory Redis needs.
AWS and GCP Marketplace
The marketplace sign-up endpoints of Future AGI Cloud (/accounts/aws-marketplace/, /accounts/gcp-marketplace/) are not served by an open-source install. The AWS Marketplace client uses only AWS_MARKETPLACE_ACCESS_KEY_ID and AWS_MARKETPLACE_SECRET_ACCESS_KEY, never the default AWS credential chain, so your Bedrock keys or instance role are never used for it.
Other outbound connections
- Model providers, SSO providers and integrations are called only when you configure them and use them.
- litellm’s model price list. Each API and worker process downloads it from
raw.githubusercontent.comwhen it starts.LITELLM_LOCAL_MODEL_COST_MAP=Truein.envuses the list bundled with the image instead, with prices as of the pinned litellm release. - Model downloads from the Hugging Face Hub. The model server,
serving, downloads each of its models the first time a feature asks for it.servingalways runs on Distributed, and runs with themlprofile on Standalone and withserving.enabledon Helm. Pre-seed its model cache and setHF_HUB_OFFLINE=1andTRANSFORMERS_OFFLINE=1to stop the downloads. - The browser UI. Users’ browsers load the UI’s fonts from
fonts.googleapis.comandfonts.gstatic.comand its icons fromapi.iconify.designon every page, and a few screens load a code editor, document previews, videos and logos from other public hosts. None of them is Future AGI. The browser UI lists each host and what an install without it loses. - The Enterprise licence. With
EE_LICENSE_KEYset, the app activates the licence withhttps://api.futureagi.com(FUTURE_AGI_LICENSE_URL) when a licensed feature first needs it, and sends a licence heartbeat every 24 hours. The heartbeat carries the licence id, the instance id, the version, the deployment type, a timestamp, a nonce and a sequence number, and the same usage counts as a telemetry heartbeat, for the last 24 hours. It is separate from deployment telemetry:FUTURE_AGI_TELEMETRY_DISABLEDdoes not stop it, andFUTURE_AGI_ENTERPRISE_HEARTBEAT_DISABLED=truedoes. - The installer.
./bin/installand.\bin\install.ps1pull images from Docker Hub, and on Distributed also fromghcr.io(the MinIO and PeerDB images), or build the Future AGI images with--from-source. Apart from that and the lookup below, they talk only to the stack they start. Before they ask for the first account’s email, they print what deployment telemetry will send and how to opt out (--no-telemetry,-NoTelemetry). - The installer’s public-IP lookup. When
VITE_HOST_APIin.envnames a host other thanlocalhostor127.0.0.1, the bash installer askshttps://ifconfig.io(thenhttps://api.ipify.orgif that fails) for the host’s public IP address, to print a public URL in its final summary. Those services see the request’s IP address. WithVITE_HOST_APIunset or local, the default, it makes no such request, and the PowerShell installer never does.
The LLM gateway’s OpenTelemetry export, described in Observability, sends gateway traces to a collector you choose and is unrelated to deployment telemetry.
The browser UI
The UI runs in each user’s browser, so these requests come from the browser, not from your server. Each host sees the browser’s IP address; the UI sends no Referer to other sites (Referrer-Policy: same-origin). None needs a key, and none of them is Future AGI.
| Host | Loaded when | Without it (an air-gapped install) |
|---|---|---|
fonts.googleapis.com, fonts.gstatic.com | Every page: the stylesheet imports Inter and IBM Plex Sans from Google Fonts. | Text uses the Inter bundled with the UI (weights 400 to 700) and system fonts. A firewall that drops these requests instead of refusing them can delay the first paint until the browser gives up. |
api.iconify.design (then api.simplesvg.com, api.unisvg.com) | Every page: each icon is fetched by name the first time it is shown, then kept in the browser’s local storage. | Icons are blank, including icon-only buttons such as close, menus and show password. |
cdn.jsdelivr.net | The code editor: code evals and their test playground, JSON eval results, Execute Code columns, tool schemas, a dataset’s Add Row. | The editor stays on “Loading…”, so code evals, code columns and tool schemas cannot be written. |
unpkg.com | Previewing a PDF in a dataset or experiment cell. | PDF preview fails. |
view.officeapps.live.com | Previewing a Word document in a dataset cell. Microsoft’s viewer receives the document’s URL and downloads the document from it. | Word preview fails. It also fails online when the file is not reachable from the internet. |
www.loom.com, cdn.loom.com | Tutorial videos: Get started, and the empty Agent definitions and Scenarios pages under Simulate. | Empty video frames. |
demo.arcade.software, app.arcade.software | Interactive tours: the Knowledge base page while it has none, and some help links. | Empty frames. |
flagcdn.com | The country-code picker of a voice agent. | No flags. |
fi-image-assets.s3.ap-south-1.amazonaws.com | Model-provider logos: model pickers, the API keys page, LLM spans. | No logos. |
cdn-icons-png.flaticon.com | Annotator avatars on a dataset’s Annotations tab. | No avatars. |
No setting serves these from the install itself yet. Without them an air-gapped install still works, apart from the code editor (and so code evals) and PDF and Word previews. Media URLs in your datasets and traces, a LiveKit server, and YouTube or Vimeo links load from wherever they point.
Analytics, error reports and ad pixels send nothing unless the UI was built with their keys, and the published images are built with none of them:
| Service | Build-time key |
|---|---|
| Mixpanel | VITE_MIXPANEL_TOKEN |
| PostHog | VITE_POSTHOG_KEY |
| Sentry | VITE_SENTRY_DSN |
| New Relic | VITE_NEWRELIC_LICENSE_KEY and an application ID; without them the agent is not started |
| Google Tag Manager | VITE_GTM_ID |
| reCAPTCHA | VITE_GOOGLE_SITE_KEY |
| Google, Reddit and X ad pixels | VITE_GOOGLE_ADS_ENABLED, VITE_REDDIT_ADS_ENABLED, VITE_TWITTER_ADS_ENABLED, each with its ID |
Restricted networks
To run an install with no outbound access, or to keep it from trying to reach outside hosts:
- Set
FUTURE_AGI_TELEMETRY_DISABLED=true, and blockapi.futureagi.comso the one minimal registration fails harmlessly. - Set
LITELLM_LOCAL_MODEL_COST_MAP=Trueso no process downloads the price list. - Leave the third-party keys above empty.
- With an Enterprise licence, decide on the licence heartbeat:
FUTURE_AGI_ENTERPRISE_HEARTBEAT_DISABLED=truestops it. - Set
HF_HUB_OFFLINE=1andTRANSFORMERS_OFFLINE=1so the model server downloads no models, after pre-seeding its model cache. - Point LLM features at a model server on your network. One added in the UI on a private address needs
AGENTCC_ALLOW_PRIVATE_PROVIDER_URLS=true: see Local and private model servers. - Route what must go out through a proxy with
HTTP_PROXY,HTTPS_PROXYandNO_PROXYin a compose override. On Distributed, list the override inCOMPOSE_FILE: see Move to managed data stores. The LLM gateway does not use a proxy yet. - Expect users’ browsers to lose the code editor, and with it the writing of code evals, and PDF and Word previews, when they cannot reach the public hosts in The browser UI.
On Helm, global.airgap=true covers telemetry, the licence heartbeat, the price list and model serving’s downloads in one value, and global.imageRegistry points every image at your mirror. See Install on Kubernetes with Helm. At a glance lists every connection and Settings every setting.
Dive deeper
Questions & Discussion