Backend service for an Excel add-in that lets users trigger AI-assisted finance workflows from a workbook. The API accepts workbook uploads and chat-style instructions, runs an agent asynchronously, and returns structured Excel operations that the add-in can render back into the workbook.
- Accepts workbook uploads and follow-up chat requests from an Excel add-in.
- Stores each conversation in a local session directory under
chats/. - Computes a compact workbook manifest with sheets, headers, samples, types, formulas, tables, named ranges, and column stats.
- Runs a general-purpose Excel agent through Celery so long-running finance tasks do not block HTTP requests.
- Lets the agent inspect workbook structure, read datasets, execute Python, inspect artifacts, and publish validated operations.
- Returns operations such as tables, cell writes, formulas, charts, conditional formatting, sorting, filtering, and pivot tables.
- Keeps older reconciliation endpoints for comparing two datasets.
Typical workflows include workbook analysis, financial summaries, reconciliation, variance checks, formatting, charting, pivot-style aggregation, and formula generation.
Excel add-in
-> FastAPI (`api.py`)
-> Redis task/session metadata
-> Celery worker (`tasks.py`)
-> ExcelAgent (`src/excel_agent.py`)
-> tool layer (`src/tools/`)
-> result operations (`result_<turn>.json`)
-> FastAPI polling response
-> Excel add-in renderer
Key components:
api.py: HTTP API for health checks, workbook chat, test fixtures, and reconciliation.tasks.py: Celery tasks for chat processing and dataset reconciliation.celery_app.py: Celery app configured with Redis broker/backend.src/excel_agent.py: OpenAI-compatible agent loop using OpenRouter by default.src/excel_agent_prompts.py: System prompt and output contract for Excel operations.src/manifest.py: Workbook manifest generation for efficient LLM context.src/tools/: Agent-visible tools for workbook inspection, dataset reads, Python execution, artifact reads, and operation publishing.src/schemas.py: Pydantic API and operation schema shared by backend responses and test fixtures.test_fixtures/: Static operation payloads for frontend renderer testing.
GET /healthReturns {"status": "ok"}.
POST /v1/chat
GET /v1/chat/{task_id}POST /v1/chat starts a new task and returns a taskId.
Supported request modes:
multipart/form-data: start a new conversation or refresh a workbook.file:.xlsxworkbookmessage: user instructioncontext: optional JSON focus hints from the add-inconversationId: optional, used when refreshing an existing conversation
application/json: follow-up message for an existing conversation.message: user instructionconversationId: existing conversation idcontext: optional focus hints
GET /v1/chat/{task_id} polls for status and returns the final message, conversationId, and Excel operations when complete.
POST /v1/chat/testReturns static operation fixtures without Redis or Celery. This is useful for testing the Excel add-in renderer.
Example messages:
test tabletest chart pietest pivot_table multi_value
POST /reconcile
GET /reconcile/{task_id}Starts and polls an asynchronous reconciliation job for two dataset paths.
The agent returns an AgentResult:
{
"operations": [],
"message": "Human-readable summary"
}Supported operation types:
tablewrite_cellsformulachartconditional_formatformatted_rangesortfilterpivot_table
The publish_operations tool validates operations against src/schemas.py before saving result_<turn>.json. FastAPI validates the Celery result again before returning it to the add-in.
Install dependencies:
uv sync --extra devCreate a local .env file. .env is ignored by Git.
cp .env.example .envCommon environment variables:
OPENROUTER_API_KEY=...
OPENROUTER_MODEL_NAME=moonshotai/kimi-k2.5
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
ANTHROPIC_API_KEY=...
MODEL_NAME=claude-sonnet-4-20250514
MAX_TURNS=20
MAX_TOKENS=4096
EXECUTION_TIMEOUT=30
REDIS_URL=redis://localhost:6379/0OPENROUTER_API_KEY is used by the general Excel chat agent. ANTHROPIC_API_KEY is used by native Anthropic/reconciliation paths.
Start Redis:
docker compose up -d agent_redisStart the API:
uv run uvicorn api:app --reload --host 127.0.0.1 --port 8000Start the worker in another terminal:
uv run celery -A celery_app worker --loglevel=info --pool=gevent --concurrency=1 --prefetch-multiplier=1The helper scripts start_api.sh and start_celery.sh do the same style of startup using a local conda environment.
Docker Compose can also run Redis, API, and worker:
docker compose up -d --buildThe compose API listens on port 9000.
Run the full test suite:
uv run --extra dev pytestThe tests cover schemas, manifest generation, prompt behavior, sandbox execution, tool behavior, fixture payloads, and chat API flow.
Tracked sample/config files intentionally include .env.example only. Real local secrets and generated data are ignored through .gitignore, including:
.env.env.localinput/uploads/chats/output/test_data/
Do not commit real workbook uploads, generated chat sessions, API keys, or provider credentials.