> For the complete documentation index, see [llms.txt](https://docs.trover.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trover.tech/engineering/x-agent-setup.md).

# X agent setup: everything is code-side; only .env remains

The agent's X channels (mentions, DMs, the 6-hourly market-radar post) are wired. The bot handle is `@troveragent` everywhere in code and templates (`BOT_X_USERNAME` default, `PROJECT_X_USERNAME` default, `X_MCP_USERNAME`, `apps/web/src/lib/constants.ts` `BOT_X_HANDLE`, `TroverEthDistributor`'s immutable `AGENT_X_URL`). What is left is the server `.env`.

## 1. Values to set (server `~/trover/.env`, backup first)

| Variable                                                | Where it comes from                                                                                                      | Notes                                                                                                                               |
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `BOT_X_USERNAME=troveragent`                            | the bot account                                                                                                          | persona prompt and mention matching                                                                                                 |
| `BOT_X_USER_ID`                                         | `GET https://api.x.com/2/users/by/username/troveragent` with the bearer token                                            | numeric id; DM polling needs it                                                                                                     |
| `PROJECT_X_USERNAME=troveragent`                        | project account (or the bot if the same)                                                                                 | interpolated into the persona                                                                                                       |
| `FOUNDER_X_USERNAME`                                    | your handle                                                                                                              | interpolated into the persona; currently unset on the server                                                                        |
| `X_API_KEY`, `X_API_SECRET`                             | Developer Portal → app → Keys and tokens → Consumer keys                                                                 | OAuth 1.0a app credentials; also the CRC/signature secret fallback                                                                  |
| `X_BEARER_TOKEN`                                        | same page                                                                                                                | app-only reads (mentions backfill, user lookup, usage)                                                                              |
| `X_CLIENT_ID`, `X_CLIENT_SECRET`                        | app → OAuth 2.0 client                                                                                                   | user-context OAuth 2.0                                                                                                              |
| `X_USER_ACCESS_TOKEN`, `X_USER_REFRESH_TOKEN`           | OAuth 2.0 user flow for **@troveragent** with scopes `tweet.read tweet.write users.read dm.read dm.write offline.access` | posting replies as the bot; refresh token is rotated by the worker                                                                  |
| `X_OAUTH1_ACCESS_TOKEN`, `X_OAUTH1_ACCESS_TOKEN_SECRET` | app → Keys and tokens → Authentication tokens, generated **while logged in as @troveragent**                             | required for the Account Activity subscription and DMs                                                                              |
| `X_WEBHOOK_ID`                                          | Developer Portal → Account Activity → the webhook registered for `https://api.trover.tech/v1/x/webhook`                  | already set on the server for the old account; re-register if the app changes                                                       |
| `X_WEBHOOK_SECRET`                                      | optional                                                                                                                 | the CRC and signature checks fall back to `X_API_SECRET` when this is empty, so leave it empty unless X gives you a separate secret |
| `ENABLE_X_ACTIVITY_WEBHOOKS=true`                       |                                                                                                                          | mention/DM delivery by webhook; polling (`ENABLE_POLLING_FALLBACK`) covers gaps                                                     |
| `ENABLE_PROACTIVE_POSTS`, `ENABLE_TREND_POSTS`          |                                                                                                                          | both `false` today; the market-radar post is off until both are `true`                                                              |

Every one of these is `optionalSecret` in `packages/core/src/env.ts`: a missing value never fails boot, it fails at call time. That is why the checks below exist.

## 2. Order of operations when the account changes

1. Regenerate the OAuth 1.0a access token pair and the OAuth 2.0 user tokens **as @troveragent** (tokens are per account, not per app).
2. Set `BOT_X_USERNAME`, `BOT_X_USER_ID`, `PROJECT_X_USERNAME`.
3. Redeploy api and worker (env is read at boot).
4. Confirm the connection and the webhook subscription (section 3).

## 3. Checks (admin key = `ADMIN_API_KEY`)

```
# who the tokens belong to, and whether it matches BOT_X_USERNAME
curl -s -H "x-api-key: $ADMIN_API_KEY" https://api.trover.tech/v1/admin/x/connection
# expected: {"authenticatedAccount":{"id":"…","username":"troveragent"},"matchesConfiguredBot":true,"webhookIdConfigured":true,"webhooksEnabled":true}

# CRC: X calls this on registration; a 200 with a response_token means the secret is right
curl -s "https://api.trover.tech/v1/x/webhook?crc_token=test"

# subscribe the bot account to the webhook (idempotent; "alreadySubscribed" is success)
curl -s -X POST -H "x-api-key: $ADMIN_API_KEY" -H "x-admin-actor: setup" https://api.trover.tech/v1/admin/x/webhook/subscribe

# monthly read budget
curl -s -H "x-api-key: $ADMIN_API_KEY" https://api.trover.tech/v1/admin/x/usage
```

Then mention the bot from another account with an NFT question ("@troveragent floor of ponsguy?"); the worker log shows `ingestXEvent` → the run → the reply, and the reply is the one-line indexed summary with the data age.

## 4. What the agent can now do on X

Everything the website chat can: wallet, portfolio, trades and bridges (with signing links), and since 2026-09-08 the indexed NFT market (floor, volume, sales, mints, lifecycle, orderbook, traits, holders, drops, trending, snipe plans, token economics). On X the reply is the deterministic ≤200-character summary; `MAX_REPLY_LENGTH` (250) still bounds it.


---

# 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.trover.tech/engineering/x-agent-setup.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.
