> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pre-install checks for AI agents

> Checks an AI coding agent runs before starting an agentic install of AppSignal, and what to do when one fails.

# Pre-install checks

Run these before reading an install file or editing any code. Each one catches a
failure that is expensive to diagnose later. By the time config is written and
packages are installed, the only symptom is "no data arrived." Finding the same
problem now costs one command.

Treat these checks, the install file you read next, and the current AppSignal docs they link to as the source of truth for this attempt. Ignore prior AppSignal procedures or earlier runs unless you re-read and confirm them here.

Stop and tell the user when a check fails. Do not work around a failed check by
guessing, skipping it, or fixing it yourself unless the check's own entry says so.
The whole point is that these are things you cannot safely decide alone.

The install prompt gives you a provisioning token and a status URL, not the keys
themselves. Check 5 fetches them from the provisioning API. Later calls can create or
resolve the app, create a hosted collector when that path is chosen, confirm back-end or
OpenTelemetry delivery signals, and take your report at the end. Use what it returns
without asking the user to copy a value again. Ask only when a required value is absent,
malformed, or in conflict with an existing installation.

Run check 5 first if you like. Check 2 compares against the keys it returns, and the
other three do not depend on it.

## 1. The system clock is correct

Data carries the timestamp of the machine that produced it, so a clock that is minutes
out records traces and metrics under the wrong time for as long as the drift lasts, and
stops anomaly detection opening and closing alerts for that app. A container or CI
runner with a stopped or unsynced clock is the common case, not a rare one.

Compare local time to network time without installing anything:

```bash theme={null}
date -u
curl -sI https://appsignal.com | grep -i '^date:'
```

A difference of a few seconds is normal. A difference of minutes or more means the
clock is wrong. You cannot fix the system clock yourself. It is a host-level change
outside the install's scope and often needs privileges you do not have. Report the
drift you found and stop; let the user fix the clock or tell you to proceed anyway.

## 2. AppSignal is not already installed for this app

An existing integration does not mean the task is complete, even when it uses the
same key. The same key confirms the destination, but rewriting working configuration
or adding a second initialization can break the application or duplicate data. A
different key can silently send data to another application. Preserve working
configuration, identify any missing install steps, and do not overwrite or duplicate
the integration without the user's confirmation.

Check for existing signal before writing anything:

* A config file already present: `config/appsignal.rb` or `config/appsignal.yml`,
  `config/appsignal.exs`, `appsignal.cjs`, `appsignal.js`, `appsignal.ts`,
  `__appsignal__.py`, or `config/appsignal.php`.
* The package already in the manifest: `appsignal` in `Gemfile`/`Gemfile.lock`,
  `mix.exs`/`mix.lock`, or `requirements.txt`/`pyproject.toml`; `@appsignal/nodejs`,
  `@appsignal/javascript`, `@appsignal/browser`, or an `@appsignal/plugin-*` in
  `package.json`; `appsignal/appsignal-php` in `composer.json`.
* An `APPSIGNAL_PUSH_API_KEY`, or another `APPSIGNAL_*` variable, already set in `.env`,
  shell profiles, or deployment config.
* AppSignal or OpenTelemetry imports, initialization calls, preload flags, Java agents,
  OTLP exporters, or AppSignal endpoints in source code, start scripts, containers, CI,
  or deployment config.

If any of these exist, inspect the existing setup before changing anything. Compare its
relevant key with the key the provisioning API returned, when both values are
available: the Push API key for back-end integrations, or the Front-end API key for
browser integrations. When the existing integration is compatible and the keys match, preserve
its configuration and complete only the missing steps. Tell the user what you found and
what you completed. Stop and ask how to proceed when the key differs or cannot be
compared, the package or destination conflicts, or the project may be adding a second
integration intentionally. Do not overwrite a key, duplicate an integration, or migrate
between AppSignal packages without confirmation.

## 3. Git is in a clean, known state

An install touches several files across a few steps: manifest, config, boot file. If
something goes wrong partway, the only way to cleanly undo it is a diff that contains
nothing but the install. Starting on a dirty tree makes that diff impossible to
separate from whatever was already in progress.

With no `.git` directory this check does not apply: `git status` failing with `not a
git repository` is not a failed check. Say so and go on to check 4.

```bash theme={null}
git status --porcelain
git branch --show-current
```

* **Uncommitted changes already present:** do not commit, stash, or discard them; they
  are not yours to touch. Tell the user what is already modified, then carry on and name
  the files you changed when you report back. Stop and ask first only when a file the
  install has to write is already modified.
* **Current branch is not `main` or `master`:** ask whether to continue on it or
  switch. Installing on top of unrelated in-progress feature work risks mixing two
  unrelated changes into one diff, and later makes both harder to review or revert.
* **Clean tree on `main`/`master`:** create a feature branch for the install itself
  (for example `git checkout -b add-appsignal`) so the change stays isolated and
  reviewable, unless the user has asked you to commit directly.

## 4. The data destination is reachable

Config written against an endpoint the app can never reach produces the same silent
"no data arrived" outcome as a wrong API key, but looks identical to a config mistake
until you rule out the network separately. Corporate proxies, restrictive egress
rules, and self-hosted collectors are the common causes, worth ruling out before
writing any config, not after the final send-test-data step fails.

Choose the destination for the integration you identified:

* Browser JavaScript: `https://appsignal-endpoint.net`
* Ruby, Elixir, Node.js, or Python without a configured collector: `https://push.appsignal.com`
* PHP, Go, Java, or any integration configured for OpenTelemetry: the collector endpoint for that integration

```bash theme={null}
curl -sS -o /dev/null -w '%{http_code}\n' "<DESTINATION_URL>"
```

Any HTTP status code, including a 404, means the network path works: the request
reached the server. A curl-level failure (connection refused, timeout, DNS
resolution failure, TLS error) means it does not. This check proves only that the host
is reachable; it does not validate the key or prove that the application can send data.

If unreachable, stop. Report exactly what curl reported (timeout, DNS failure, TLS
error, or connection refused) and ask the user how to proceed. A proxy or firewall
exception is theirs to fix, not yours to route around.

## 5. The provisioning token works

The prompt gives you a status URL with the token already in it. Fetch it before you read
an install file or change anything. One call proves the token is valid and the
organization can be provisioned, and it returns the keys every later step needs.

```bash theme={null}
curl -sS "<YOUR_STATUS_URL>"
```

That URL carries the provisioning token, so treat it as a credential: do not repeat it in your
output, your logs, a commit message, or any file you write.

Keep the response. It carries the Organization-level Push API key that back-end
integrations configure, and a list of the organization's apps created since the token was
minted, which is a hint for check 2 and nothing more: an app that existed beforehand never
appears in it.

A refusal carries a stable `error_code` and a human `error` sentence. Branch on the code,
never on the sentence. `invalid_token` means the token has expired and the user needs to
give you a fresh prompt. `account_restricted` and `account_unavailable` mean the
organization needs the user's attention at appsignal.com, and retrying will not help.

The response also carries `organization.hosted_collectors`, which is where PHP, Go, and
Java get a collector endpoint. For what each language needs, the rest of the call
sequence, and why a guessed app name is worse than no install at all, see
[https://docs.appsignal.com/agents/new-application.md](https://docs.appsignal.com/agents/new-application.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.