Don’t want to read all this?
Just drop a link to https://xedant.com/agents/research/install.md or to https://xedant.com/llms.txt into any AI chat (Claude, ChatGPT, etc.) and ask it to generate the config files and commands. It will read the docs, ask you a few questions about your setup, and hand you a ready-to-use configuration. Save time — let the model do the reading for you.
You can also reach me on Telegram — I’m always glad to help. And that’s not just politeness — I genuinely enjoy talking to like-minded people, especially if you love coding as much as I do.
Xedant Research Agent is a self-hosted web application for deep online research, planning, and documentation. It runs as a single Docker container (Docker is a tool that packages an app with everything it needs, so it runs the same way on any server), and keeps all data in a permanent volume mounted at /data. Integration with Xedant Agent is optional and turns on with two environment variables.
Minimum requirements
Any Linux host with Docker is enough. The SQLite database is built in — PostgreSQL connects optionally through an environment variable.
For full functionality you will also need (configured in the interface after launch, not in environment variables):
- An API key for at least one search provider — Serper, Keenable, Brave, or Tavily (or your own SearXNG, or JsonSeo — results from Yandex, Google, or Bing);
- An LLM provider API key for data extraction — any OpenAI-compatible service.
Docker Compose
Create a compose.yml file and run docker compose up -d:
services:
research-agent:
image: xedant/research-agent:latest
container_name: research-agent
ports:
- "3978:80"
volumes:
- research-agent-data:/data
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80
restart: unless-stopped
volumes:
research-agent-data:
After launch, the interface is available on port 3978: http://localhost:3978.
Environment variables
Every variable is optional — the application starts and works without a single one:
- RESEARCH_AGENT_DB — path to the SQLite file (default
/data/data.db) or a PostgreSQL connection string likeHost=...;Port=...;Database=.... - RESEARCH_AGENT_API_KEY — enables the agent API (
/api/agent/*) for calls from external agents: they pass the key in theX-API-Keyheader. Without the variable, the API returns 503. This is a separate mechanism — it is not tied to the JWT authentication of the web interface. - RESEARCH_AGENT_FETCH_FOLDER — folder for downloaded Markdown (default
/data/fetch). Files are organized by date:{folder}/yyyy-MM-dd/{domain}_{slug}_{hash8}.md. - AGENT_API_URL and AGENT_API_KEY — enable integration with Xedant Agent: the “Call Agent” and “Edit with AI” buttons on research pages, agent chats, and the shared prompt queue. Set them together, otherwise the features stay hidden. The outgoing request goes to
{AGENT_API_URL}/api/remote/chats. - RESEARCH_AGENT_ERROR_REPORTING — sends errors to Sentry. Set
0to disable. - ASPNETCORE_URLS — the port inside the container (default
http://+:80). - RESEARCH_AGENT_SSL — automatic HTTPS: the value
autoturns on generation of a self-signed certificate and an HTTPS port (by default, the one right after the HTTP port). - RESEARCH_AGENT_BASE_PATH — the subfolder the interface is served from (for example,
/research), when the application is published behind a proxy at an address likeexample.com/research. - RESEARCH_AGENT_CLICKHOUSE_URL — connection string for an external ClickHouse database (for example,
Host=...;Port=8123;Username=...;Password=...). It turns on background export of research statistics to that database — useful when you want your own analytics outside the application. The database and table are created automatically on first run; until the variable is set, nothing is exported. - SSO_PROXY_TOKEN — the shared single sign-on (SSO) secret used when several services sit behind one gateway (nginx, for example): a user already logged in to the gateway enters Research Agent automatically, without a second login. A user in the
managergroup gets administrator rights. Without the secret, regular login and password sign-in works.
Data storage
All permanent data lives in the /data volume and survives container recreation. The volume is mandatory — without it you will lose the database, downloaded research, and keys on the very first docker compose down.
/data/data.db— the SQLite database (when PostgreSQL is not used);/data/auth/— ASP.NET Data Protection keys;/data/keys/— the JWT signing key;/data/fetch/— downloaded Markdown, organized by date.
Downloaded pages are temporary history: a background sweeper deletes them two days after the download (the window is set by the RESEARCH_AGENT_FETCH_RETENTION_HOURS variable, 48 hours by default). What is worth keeping is the finished reports in the library, not the source pages.
The exception is research statistics: when the export is enabled (the RESEARCH_AGENT_CLICKHOUSE_URL variable), it is written to a separate external ClickHouse database, not to the volume — the ClickHouse server itself runs outside the container.
First sign-in
The login and password are not set through environment variables. The first user registers right in the web form on the sign-in page: login, password (4 characters or more), name, and email. The password is stored as an SHA-256 hash, and the session works through JWT tokens.
Setup after launch
Search providers and models are configured in the Services section of the web interface — not through environment variables. There you set the API keys for Serper, Keenable, Brave, Tavily, and JsonSeo, the base URL of your own SearXNG, and the services for downloading pages: Direct HTTP works right away, Proxied HTTP needs a proxy address, Remote Browser needs the address of an external service, and the local browsers (Browser Emulation and Nodriver) download everything they need on their own. LLM services are configured for data extraction. Every service can be tested right from the interface. Details in the Services & Models section.
Version and updates
The current version of Research Agent is 0.1.20. Images are published on docker.io (xedant/research-agent:latest), so an update is two commands: docker compose pull and docker compose up -d. The version number is visible in the interface, and after an update it refreshes itself: the application notices the new version after reconnecting and refreshes the interface — nothing to do by hand.
Deployment modes
The interface can be installed as an application: Research Agent serves a PWA manifest, so on a phone or desktop it opens in its own window like a regular program. If you need HTTPS, enable RESEARCH_AGENT_SSL=auto — the server will issue a self-signed certificate itself and open an HTTPS port next to the HTTP one. When hosting behind a proxy at an address with a subfolder (for example, example.com/research), specify it in RESEARCH_AGENT_BASE_PATH — all interface URLs will be built with that subfolder in mind.
Connection with Xedant Agent
To control the agent from the research interface, set the AGENT_API_URL and AGENT_API_KEY variables — agent chats with real-time updates and the “Call Agent” button in documents will appear. Details in the Xedant Agent Integration section.
Docker CLI with a .env file
You can also run Research Agent without compose — with a docker run command, keeping the environment variables in a .env file:
# .env
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://+:80
# optional: PostgreSQL instead of the built-in SQLite
# RESEARCH_AGENT_DB=Host=postgres;Port=5432;User Id=research;Password=secret;Database=research;
# optional: Xedant Agent integration
# AGENT_API_URL=
# AGENT_API_KEY=
docker run -d \
--name research-agent \
--env-file .env \
-p 3978:80 \
-v research-agent-data:/data \
--restart unless-stopped \
xedant/research-agent:latest
The --env-file flag reads all variables from the file. Individual values can be overridden with additional -e flags after it, for example -e RESEARCH_AGENT_API_KEY=your-key.