Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ivory.finance/llms.txt

Use this file to discover all available pages before exploring further.

The /v1/rag/answer/agent endpoint is fully model-agnostic and multi-tenant. Every request can include an optional config object that controls which AI provider, model, and database the agent uses — enabling completely isolated per-client agents.
{
  "query": "What was AWS revenue in Q4 2025?",
  "config": {
    "llm_provider": "anthropic",
    "llm_model": "claude-opus-4-6",
    "db_connection_string": "postgresql://user:pass@your-host:5432/your_db"
  }
}
All config fields are optional. Omit the entire config object (or any field within it) to use the server defaults (OpenAI GPT-4o + the Ivory Finance Postgres database).

LLM Providers

The agent supports two AI providers. Both power the same tool-calling loop and streaming answer generation.

OpenAI

The default provider. Uses the OpenAI Chat Completions API with function calling.
FieldValue
llm_provider"openai"
llm_modelSee model table below
Required keyOPENAI_API_KEY on the server

Available models

ModelBest forSpeed
gpt-4o (default)Best accuracy, complex multi-step reasoning~2–4s
gpt-4o-miniLower cost, simple queries~0.5–1s
o1Advanced reasoning, mathematical queries~5–15s
o3-miniFast reasoning tasks~2–5s

Example request

{
  "query": "What were Tesla's gross margins in the last three quarters?",
  "cik": "0001318605",
  "config": {
    "llm_provider": "openai",
    "llm_model": "gpt-4o"
  }
}
OpenAI is the default. If you omit the config field entirely, GPT-4o is used automatically.

Getting your OpenAI API key

1

Create an OpenAI account

Go to platform.openai.com and sign up or log in.
2

Navigate to API Keys

Click your profile icon → API KeysCreate new secret key.
3

Add billing

Go to Settings → Billing and add a payment method. Without credits the API returns 429 errors.
4

Provide the key

Contact support@ivory.finance with your key to have it configured for your account. The key is stored encrypted and never exposed in API responses.
API keys are sensitive credentials. Never include them in client-side code or public repositories. Always provision them server-side through the Ivory Finance support team. Keys are encrypted at rest using AES-256 and are never returned in API responses.

Web Search Providers

The web_search and news_search tools use a configurable search provider. Set config.search_provider to choose the engine, and supply config.search_api_key or config.search_custom_url when required.

Google

The default provider. No API key required from the caller — Google Search is available out of the box.
FieldValue
search_provider"google" (default)
search_api_keyNot required

Sub-engines available

The Google provider also supports additional data sources via the service field:
service valueDescription
google (default)Broad web results
wikipediaDefinitions and explanations
arxivAcademic and quantitative research
redditRetail investor sentiment
xReal-time social commentary
yahooFinance news and portals
reutersPremium financial wire (news search)

Example request

{
  "query": "What is NVIDIA's competitive position in AI chips?",
  "config": {
    "search_provider": "google"
  }
}
Google is the default. Omitting search_provider entirely uses Google Search automatically.

Database Connections

The query_database tool lets the agent run structured queries against your own database. This is useful when you have proprietary financial data — internal earnings models, client portfolios, custom metrics — that you want the agent to combine with SEC filing data. Pass your database connection string in config.db_connection_string. The database type is auto-detected from the URL scheme.

PostgreSQL

The most commonly used relational database. Uses the psycopg2 driver.

Connection string format

postgresql://username:password@hostname:5432/database_name

Example

{
  "query": "What were our top 5 client holdings by value last quarter?",
  "config": {
    "db_connection_string": "postgresql://analyst:s3cr3t@db.mycompany.com:5432/portfolio_db"
  }
}

The agent writes SQL like this

SELECT client_id, ticker, SUM(market_value) AS total_value
FROM holdings
WHERE quarter = '2025-Q4'
GROUP BY client_id, ticker
ORDER BY total_value DESC
LIMIT 5

Hosted PostgreSQL services

ServiceConnection string format
Supabasepostgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
Neonpostgresql://[user]:[pass]@[host].neon.tech:5432/[db]?sslmode=require
AWS RDSpostgresql://[user]:[pass]@[endpoint].rds.amazonaws.com:5432/[db]
Google Cloud SQLpostgresql://[user]:[pass]@[ip]:5432/[db]
Azure Databasepostgresql://[user]@[server]:[pass]@[server].postgres.database.azure.com:5432/[db]
Ivory Finance recommends creating a read-only database user specifically for agent queries. The agent only issues SELECT statements, but defence-in-depth matters.
CREATE USER ivory_agent WITH PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE your_db TO ivory_agent;
GRANT USAGE ON SCHEMA public TO ivory_agent;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO ivory_agent;

Data Warehouses & Lakehouses

The agent supports the four most common cloud data platforms in addition to traditional databases. Pass the appropriate connection string in config.db_connection_string — the type is auto-detected from the URL scheme.

Snowflake

Uses the official snowflake-connector-python driver.

Connection string format

snowflake://username:password@account_identifier/database/schema?warehouse=WH_NAME&role=ROLE_NAME
URL componentDescription
account_identifierYour Snowflake account locator, e.g. xy12345.us-east-1
databaseSnowflake database name
schemaOptional schema name (e.g. PUBLIC)
warehouseVirtual warehouse to use (query param)
roleOptional role override (query param)

Example

{
  "query": "What were our top revenue-generating products last quarter?",
  "config": {
    "db_connection_string": "snowflake://analyst:s3cr3t@xy12345.us-east-1/FINANCE_DB/PUBLIC?warehouse=COMPUTE_WH&role=ANALYST_ROLE"
  }
}

The agent writes SQL like this

SELECT product_name, SUM(revenue) AS total_revenue
FROM FINANCE_DB.PUBLIC.sales_summary
WHERE quarter = '2025-Q4'
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 20
Create a read-only Snowflake role for agent access:
CREATE ROLE ivory_agent;
GRANT USAGE ON WAREHOUSE compute_wh TO ROLE ivory_agent;
GRANT USAGE ON DATABASE finance_db TO ROLE ivory_agent;
GRANT USAGE ON SCHEMA finance_db.public TO ROLE ivory_agent;
GRANT SELECT ON ALL TABLES IN SCHEMA finance_db.public TO ROLE ivory_agent;
CREATE USER ivory_agent_user PASSWORD='strong_password' DEFAULT_ROLE=ivory_agent;
GRANT ROLE ivory_agent TO USER ivory_agent_user;

Security Model

Read-Only Enforcement

The agent rejects any non-SELECT statement for SQL databases. MongoDB queries are restricted to find operations — insert, update, delete, drop are blocked at the driver level.

Encrypted at Rest

Connection strings stored on the Ivory Finance server are encrypted with AES-256 (Fernet). They are never logged, never returned in API responses, and never shared between accounts.

Row Cap

All database queries are capped at 100 rows. This prevents the agent from accidentally consuming large amounts of context or triggering expensive full-table scans.

Per-Request Isolation

Each request with a db_connection_string uses a fresh, short-lived connection that is closed immediately after the query. There is no connection pooling across requests.
Use a dedicated read-only database user. Never provide superuser or admin credentials. Ivory Finance enforces SELECT-only at the application layer, but having a restricted DB user is an additional layer of defence.

Full Configuration Reference

{
  "query": "string — required",
  "company_name": "string — optional company name hint",
  "cik": "string — optional SEC CIK (zero-padded 10 digits)",
  "config": {
    "llm_provider": "openai | anthropic  (default: openai)",
    "llm_model": "gpt-4o | gpt-4o-mini | claude-opus-4-6 | claude-sonnet-4-6 | ...  (default: gpt-4o)",
    "search_provider": "google | bing | duckduckgo | custom  (default: google)",
    "search_api_key": "string — Bing subscription key or custom bearer token  (default: null)",
    "search_custom_url": "string — base URL for custom search provider  (default: null)",
    "db_connection_string": "postgresql:// | mysql:// | mariadb:// | mongodb:// | oracle:// | redshift:// | snowflake:// | databricks:// | bigquery://  (default: server Postgres)"
  }
}

Code Examples

import httpx
import json

url = "https://api.ivory.finance/v1/rag/answer/agent"
headers = {
    "X-API-Key": "your_ivory_api_key",
    "Accept": "text/event-stream",
    "Content-Type": "application/json",
}
body = {
    "query": "What were Microsoft's cloud revenue figures in the last four quarters?",
    "cik": "0000789019",
    "config": {
        "llm_provider": "openai",
        "llm_model": "gpt-4o",
        "db_connection_string": "postgresql://user:pass@your-db.com:5432/financials"
    }
}

with httpx.stream("POST", url, headers=headers, json=body, timeout=60) as r:
    for line in r.iter_lines():
        if line.startswith("data: "):
            event = json.loads(line[6:])
            if event["type"] == "token":
                print(event["token"], end="", flush=True)
            elif event["type"] == "agent_step":
                print(f"\n[{event['status']}] {event['tool']}")
            elif event["type"] == "done":
                print("\n\nDone.")
                break