Installation

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 web application for deep online research, planning, and documentation that runs on your own server. It deploys 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), with the data and the research tree kept in two permanent volumes: /apps/research — the database, keys, and downloaded pages, and /project/apps/research — reports, plans, and service settings. 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.

The product is sparing with server resources. While idle the processor is not loaded: background handlers do not poll the database on a timer, they wake up when there is work. After 15 minutes without activity the memory in use is released — the document search index, the query cache, the ClickHouse connection — and everything comes back on its own at the next task. So Research Agent sits comfortably alongside other services on one server.

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:min-latest
    container_name: research-agent
    ports:
      - "3978:80"
    volumes:
      - research-agent-data:/apps/research
      - research-agent-docs:/project/apps/research
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:80
      - RESEARCH_APP_DATA=/apps/research
      - RESEARCH_APP_DOCS_FOLDER=/project/apps/research
    restart: unless-stopped

volumes:
  research-agent-data:
  research-agent-docs:

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_APP_DATA — the folder for permanent data: the database, keys, and downloaded pages (default /apps/research);
  • RESEARCH_APP_DOCS_FOLDER — the research tree folder shown in the interface (default /project/apps/research). It is a separate volume: document contents are not baked into the image, and the folder is visible outside the container — easy to put in git or copy to another server;
  • RESEARCH_APP_DB — path to the SQLite file (default /apps/research/data.db) or a PostgreSQL connection string like Host=...;Port=...;Database=....
  • RESEARCH_APP_HASH — enables the agent API (/api/agent/*) for calls from external agents: they pass the key in the X-API-Key header. The variable holds the key’s SHA-256 hash, never the plaintext key. 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_APP_FETCH_FOLDER — folder for downloaded Markdown (default /apps/research/fetch). Files are organized by date: {folder}/yyyy-MM-dd/{domain}_{slug}_{hash8}.md.
  • RESEARCH_APP_SETTINGS_FILE — path to the service settings file (default {documents root}/settings.yml). Details in the Services & Models section.
  • RESEARCH_APP_ENV_FILE — path to the file with environment variables (default /project/.env). The file is read at startup and re-read on the fly — see “The .env file in the project folder” below.
  • 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_APP_ERROR_REPORTING — sends errors to Sentry. Set 0 to disable.
  • ASPNETCORE_URLS — the port inside the container (default http://+:80).
  • RESEARCH_APP_SSL — automatic HTTPS: the value auto turns on generation of a self-signed certificate and an HTTPS port (by default, the one right after the HTTP port).
  • RESEARCH_APP_BASE_PATH — the subfolder the interface is served from (for example, /research), when the application is published behind a proxy at an address like example.com/research.
  • RESEARCH_APP_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 manager group gets administrator rights. Without the secret, regular login and password sign-in works.

Data storage

Permanent data lives in two volumes and survives container recreation. The data volume holds the database, keys, and downloaded pages; the documents volume holds the research tree together with the service settings. Both volumes are mandatory — without them you will lose the database, downloaded research, and keys on the very first docker compose down.

  • /apps/research/data.db — the SQLite database (when PostgreSQL is not used);
  • /apps/research/auth/ — ASP.NET Data Protection keys;
  • /apps/research/keys/ — the JWT signing key;
  • /apps/research/fetch/ — downloaded Markdown, organized by date;
  • /apps/research/search-index/ — the full-text document search index: it lives on disk and is reused across restarts, so search works right after a restart;
  • /apps/research/venv/ — the Python environment shared by page downloading and by your scripts: the application prepares and updates it on its own;
  • /apps/research/scripts/ — script working folders (where a script keeps its state between runs) and service files of the prepared code;
  • /project/apps/research/ — the research tree (reports, plans, categories), the script definitions folder scripts/, and the service settings file settings.yml. A separate volume: its contents can be edited from outside, kept in version control, and moved to another server.

Downloaded pages are temporary history: a background sweeper deletes them two days after the download (the window is set by the RESEARCH_APP_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_APP_CLICKHOUSE_URL variable), it is written to a separate external ClickHouse database, not to the volumes — the ClickHouse server itself runs outside the container.

The .env file in the project folder

If the project folder contains a .env file (by default /project/.env), the application reads it at startup and re-reads it on the fly. It is a convenient place for environment variables and secrets you would rather not spell out in compose.yml: $NAME references in service settings, passwords, branding. The format is simple: a KEY=value line, comments start with #, an optional export prefix does no harm, and values are taken literally. A file with passwords is not kept in version control. The path to the file can be changed with the RESEARCH_APP_ENV_FILE variable.

Settings read at startup (the database connection string, the Xedant Agent address and key, the paths to the Python environment) take effect after the container restarts. Everything else — substituting references in service settings, the license key, the variables seen by the page downloading tools and by your scripts — is picked up on the fly, without a restart. A variable already set in the container environment or through -e stays in charge: the file does not override it, only adds to it; values removed from the file are unset.

First sign-in

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. For automated deployments that same user can be pre-set with the RESEARCH_APP_LOGIN and RESEARCH_APP_PASSWORD variables — the user is created at startup, and a changed password is updated. The password here is given as an SHA-256 hash; it can be computed right on the sign-in page, in the SHA256 generator section.

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.42. Images are published on docker.io (xedant/research-agent:min-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_APP_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_APP_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_APP_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:/apps/research \
  -v research-agent-docs:/project/apps/research \
  --restart unless-stopped \
  xedant/research-agent:min-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_APP_HASH=<sha256-of-your-key>.

← Back to the Research Agent home page