> For the complete documentation index, see [llms.txt](https://docs.sealights.io/knowledgebase/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/python-agent/capturing-coverage-from-runtime-application/running-backend-server-using-sealights-agent.md).

# Running Your Backend Server with  SeaLights

The SeaLights agent loads inside the Python process at startup to capture code coverage. It needs `SL_TOKEN`, `SL_BUILDSESSIONIDFILE`, and `SL_LABID` to report that coverage correctly.

### TL;DR — which method should I use?

<table><thead><tr><th width="229">Method</th><th width="312.75">Situation</th><th>Launch method</th></tr></thead><tbody><tr><td><strong>Method 1: Python startup hook</strong></td><td>You control the runtime environment; use it by default because it's non-intrusive (needs no code changes).</td><td><code>python app.py</code>, custom runner, Uvicorn (standalone)</td></tr><tr><td><strong>Method 2: <code>sl-python</code> wrapper</strong></td><td>You cannot change the image or <code>PYTHONPATH</code>; it requires modifying the launch command.</td><td>Any</td></tr><tr><td><strong>Method 3: Server-specific integration</strong></td><td>You run Gunicorn or uWSG servers that fork workers after startup.</td><td>uWSGI, Gunicorn</td></tr></tbody></table>

***

### Required SeaLights Configuration

Before starting the application, provide these three runtime values:

SeaLights reads these variables only when the process starts. Restart or redeploy after changing them.

1. **`SL_TOKEN`** — the SeaLights agent token. Supply it from a secret store.
2. **`SL_BUILDSESSIONIDFILE`** — the path to the generated build session ID file. A prior SeaLights CLI or CI step generates the build session ID.&#x20;
   * Keep it alongside the application when possible.
   * Use `./buildSessionId.txt` locally or `/app/buildSessionId.txt` in an image.
   * Kubernetes injection uses `/sealights/buildSessionId.txt`.
3. **`SL_LABID`** — identifies the test environment, such as `staging` or `uat` where this run's coverage rolls up.
   * Every process, container, worker, and replica in that testing environment must use the same value.
   * In addition, SeaLights assigns each runtime instance a unique Agent ID.

For a quick local check, install the agent:

```sh
pip install sealights-python-agent
```

{% hint style="info" %}
The examples below use quick-install commands. For production deployments, follow the instructions in "[Downloading the Python Agent](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/python-agent/downloading-the-python-agent.md)" and your organization's delivery practices.
{% endhint %}

***

### Method 1 — Python startup hook (recommended)

Create a `sitecustomize.py` file containing:

```python
import python_agent.init
```

Python automatically imports `sitecustomize.py` during startup. Its directory must be discoverable through `PYTHONPATH` or Python's site search path.

```
sitecustomize.py
  ↓
PYTHONPATH points to its directory
  ↓
Python imports sitecustomize.py
  ↓
SeaLights agent loads
```

This is the recommended default. It requires no application code changes.

<details>

<summary>Local validation or POC</summary>

Use this approach to validate instrumentation locally. It suits proof-of-concept work and troubleshooting. Do not use it as production installation guidance.

**Bash**

`SEALIGHTS_TOKEN` must already be exported from your secret store. This script reads it; it does not provide it.

```bash
pip install sealights-python-agent
mkdir -p .sealights
printf 'import python_agent.init\n' > .sealights/sitecustomize.py

export PYTHONPATH="$PWD/.sealights${PYTHONPATH:+:$PYTHONPATH}"
export SL_TOKEN="$SEALIGHTS_TOKEN"
export SL_BUILDSESSIONIDFILE="$PWD/buildSessionId.txt"
export SL_LABID="local-validation"

python app.py
```

**PowerShell**

`SEALIGHTS_TOKEN` must already be exported from your secret store. This script reads it; it does not provide it.

```powershell
pip install sealights-python-agent
New-Item -ItemType Directory -Force .sealights | Out-Null
Set-Content .sealights/sitecustomize.py "import python_agent.init"

$env:PYTHONPATH = "$PWD/.sealights"
$env:SL_TOKEN = $env:SEALIGHTS_TOKEN
$env:SL_BUILDSESSIONIDFILE = "$PWD/buildSessionId.txt"
$env:SL_LABID = "local-validation"

python app.py
```

</details>

Prefer Kubernetes injection over the Dockerfile approach when you do not own the image build.

{% tabs %}
{% tab title="Kubernetes injection" %}
Use this when you already have an application image. The init container writes the agent and `sitecustomize.py` to a shared volume. The application loads them through `PYTHONPATH`.

<pre class="language-yaml"><code class="lang-yaml">spec:
  volumes:
    - name: sealights
      emptyDir: {}
  initContainers:
    - name: inject-sealights
      image: python:3.11.9-slim
<strong>      command:
</strong>        - sh
        - -c
        - |
          pip install --no-cache-dir --target /sealights sealights-python-agent
          printf 'import python_agent.init\n' > /sealights/sitecustomize.py
      volumeMounts:
        - name: sealights
          mountPath: /sealights
  containers:
    - name: app
      image: registry.example/myapp:latest
      env:
        # Path to `sitecustomize.py` file created above
        - name: PYTHONPATH
          value: /sealights
        # Token from Kubernetes secret
        - name: SL_TOKEN
          valueFrom:
            secretKeyRef:
              name: sealights
              key: token
        # File containing the Build Session ID (BSID)
        # Recommended: package and deploy this file as part of the application artifact
        # Alternatively, BSID can be supplied directly via corresponding Env var
<strong>        - name: SL_BUILDSESSIONIDFILE
</strong>          value: /app/buildSessionId.txt
        # Test Environment Identifier
        - name: SL_LABID
          value: uat1
        # Logging (Optional)
        #- name: SL_DEBUG
        #  value: true
  volumeMounts:
    - name: sealights
      mountPath: /sealights
      readOnly: true
</code></pre>

{% endtab %}

{% tab title="Dockerfile-based deployment" %}
This pattern is recommended when you own the image build. The image contains the SeaLights agent configuration and artifact-specific settings (such as the BSID file location), while the deployment supplies environment-specific configuration such as the token and Lab ID.

**Dockerfile**

```dockerfile
FROM python:3.11.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
    && pip install --no-cache-dir sealights-python-agent
COPY . .
RUN mkdir /opt/sealights \
    && printf 'import python_agent.init\n' > /opt/sealights/sitecustomize.py

# SeaLights bootstrap path
ENV PYTHONPATH=/opt/sealights
# BSID file packaged with the app
ENV SL_BUILDSESSIONIDFILE=/app/buildSessionId.txt

CMD ["python", "app.py"]
```

**Kubernetes runtime configuration**

```yaml
env:
  # SeaLights token from K8s secrets
  - name: SL_TOKEN
    valueFrom:
      secretKeyRef:
        name: sealights
        key: token
  # Test environment identifier
  - name: SL_LABID
    value: uat1
  # Logging (Optional)
  #- name: SL_DEBUG
  #  value: true
```

{% endtab %}
{% endtabs %}

### Method 2 — `sl-python` wrapper

The agent ships with an `sl-python` CLI that wraps any Python invocation. Use this when you cannot modify the application source or `PYTHONPATH`, but you can change the launch command.

The first argument after `run` must be an executable.

{% hint style="info" %}
TODO: confirm signal-forwarding behavior of `sl-python run`.
{% endhint %}

{% tabs %}
{% tab title="Bash" %}

```bash
export SL_TOKEN="$SEALIGHTS_TOKEN"
export SL_BUILDSESSIONIDFILE="$PWD/buildSessionId.txt"
export SL_LABID="local-validation"

sl-python run --labId "$SL_LABID" -- python app.py
```

{% endtab %}

{% tab title="PowerShell" %}

```powershell
$env:SL_TOKEN = $env:SEALIGHTS_TOKEN
$env:SL_BUILDSESSIONIDFILE = "$PWD/buildSessionId.txt"
$env:SL_LABID = "local-validation"

sl-python run --labId $env:SL_LABID -- python app.py
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
See [Command Reference - \`run\` command](https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/python-agent/command-reference#pull-request-session-id-2)
{% endhint %}

### Method 3 — Server-specific integration

Use this method only for Gunicorn or uWSGI. These servers fork workers after startup. Each worker must load the agent after it forks.

{% tabs %}
{% tab title="Gunicorn" %}
Load the agent from Gunicorn's `post_fork` hook:

```python
# gunicorn.conf.py
import os

def post_fork(server, worker):
    import python_agent.init
```

Gunicorn runs `post_fork` for every worker. This ensures each worker loads the agent.

Provide `SL_TOKEN`, `SL_BUILDSESSIONIDFILE`, and `SL_LABID` through the Gunicorn process environment.
{% endtab %}

{% tab title="uWSGI" %}
Load the agent in every worker:

```ini
# sealights.ini
[uwsgi]
# Enables agent reporting threads
enable-threads = true
# Uses one interpreter per worker
single-interpreter = true
# Loads the application after worker fork
lazy-apps = true
# Loads the agent in every worker
import = python_agent.init
```

Provide `SL_TOKEN`, `SL_BUILDSESSIONIDFILE`, and `SL_LABID` through the uWSGI process environment.
{% endtab %}
{% endtabs %}

### Troubleshooting & FAQ

See these checks when coverage does not appear.

<details>

<summary>Coverage not appearing?</summary>

**General checks**

* Confirm the agent and `SL_TOKEN` are available.
* Confirm `SL_BUILDSESSIONIDFILE` points to an existing file.
* Verify the runtime through the Live Agents API.

**Method 1 — Python startup hook**

* Confirm `sitecustomize.py` exists.
* Confirm `PYTHONPATH` points to its directory.

**Method 3 — Gunicorn and uWSGI**

* For Gunicorn, confirm `post_fork` imports `python_agent.init`.
* For uWSGI, confirm `lazy-apps`, `single-interpreter`, and `enable-threads` are enabled.

</details>

<details>

<summary>Kubernetes runtime and permission checks</summary>

Match the init container's Python version to the application runtime.

For non-root containers, ensure the application can read the shared volume:

```yaml
securityContext:
  fsGroup: 1001
```

</details>

### See also

Use [CI-managed Python Agent Injection](/knowledgebase/setup-and-configuration/troubleshooting-faq/python/how-can-i-use-the-sealights-python-agent-without-modifying-my-repository.md) when deployment configuration is your only change point.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/python-agent/capturing-coverage-from-runtime-application/running-backend-server-using-sealights-agent.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
