Agent API Keys
HatiData provides a fine-grained API key system designed for AI agent environments. Each agent gets its own key with specific capabilities, scopes, and resource limits -- enabling per-agent billing, audit attribution, and policy enforcement.
Key Format
API keys follow a predictable format that indicates their environment:
| Prefix | Environment | Example |
|---|---|---|
hd_live_ | Production | hd_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 |
hd_test_ | Development / Test | hd_test_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4 |
Production keys (hd_live_*) are used for live deployments and have full billing metering enabled. Test keys (hd_test_*) are used during development and do not count toward billing quotas.
API Scopes
Keys are authorized using 22 granular scopes organized into four bundles. Each scope controls access to a specific API capability.
Scope Bundles
| Bundle | Scopes Included | Use Case |
|---|---|---|
read_only | query:read, tables:list, tables:describe, schemas:read, audit:read | BI tools, read-only agents |
developer | All read_only scopes + query:write, tables:create, tables:alter, functions:execute, branches:create, branches:merge | Development agents, CI/CD |
admin | All developer scopes + users:manage, keys:manage, policies:manage, orgs:manage, billing:manage, webhooks:manage | Human administrators |
agent | query:read, query:write, tables:list, tables:describe, memory:read, memory:write, cot:write, triggers:read, branches:create | AI agents with standard capabilities |
Individual Scopes
| Scope | Description |
|---|---|
query:read | Execute SELECT queries |
query:write | Execute INSERT, UPDATE, DELETE |
tables:list | List available tables |
tables:describe | Get column schemas |
tables:create | Create new tables |
tables:alter | Modify table schemas |
schemas:read | Read schema metadata |
functions:execute | Execute stored functions |
memory:read | Search and retrieve agent memories |
memory:write | Store new agent memories |
cot:write | Write chain-of-thought traces |
triggers:read | List and test semantic triggers |
triggers:manage | Create, update, delete triggers |
branches:create | Create state branches |
branches:merge | Merge branches back to main |
audit:read | Read audit logs |
users:manage | Create and manage users |
keys:manage | Create and revoke API keys |
policies:manage | Create and manage ABAC policies |
orgs:manage | Manage organization settings |
billing:manage | View and manage billing |
webhooks:manage | Manage webhook subscriptions |
Creating Agent Keys
Via the Dashboard
- Navigate to Settings > API Keys in the HatiData dashboard.
- Click Create Key.
- Fill in:
- Name: A descriptive name (e.g., "LangChain Production Agent")
- Scope Bundle: Select a bundle or customize individual scopes
- Agent ID: The agent identifier this key is bound to
- Expiration: Optional expiration date
- IP Allowlist: Optional list of allowed IP addresses
- Click Create.
- Copy the key immediately -- it will not be shown again.
Via the API
curl -X POST https://control.hatidata.com/v1/api-keys \
-H "Authorization: Bearer hd_live_admin_key" \
-H "Content-Type: application/json" \
-d '{
"name": "langchain-agent-prod",
"scopes": ["query:read", "tables:list", "tables:describe", "memory:read", "memory:write"],
"agent_id": "langchain-prod-01",
"expires_at": "2026-01-01T00:00:00Z",
"ip_allowlist": ["10.0.1.0/24", "172.16.0.0/16"]
}'
Response:
{
"key_id": "key_abc123",
"key": "hd_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"name": "langchain-agent-prod",
"scopes": ["query:read", "tables:list", "tables:describe", "memory:read", "memory:write"],
"agent_id": "langchain-prod-01",
"expires_at": "2026-01-01T00:00:00Z",
"created_at": "2025-01-15T10:30:00Z"
}
Via Python SDK
from hatidata_agent import HatiDataAgent
admin = HatiDataAgent(
host="control.hatidata.com",
port=8080,
agent_id="admin",
password="hd_live_admin_key",
)
key = admin.create_api_key(
name="crewai-analyst",
scopes=["query:read", "tables:list", "tables:describe", "memory:read", "memory:write", "cot:write"],
agent_id="crewai-analyst-01",
expires_at="2026-06-01T00:00:00Z",
)
print(f"New key: {key['key']}")
IP Allowlisting
API keys can be restricted to specific IP addresses or CIDR ranges:
{
"ip_allowlist": [
"10.0.1.100",
"10.0.2.0/24",
"172.16.0.0/16"
]
}
When an IP allowlist is set, requests from any other IP address are rejected with a 403 Forbidden response, even if the API key is otherwise valid.
For agent deployments:
- Kubernetes: Use the pod CIDR range
- Cloud Run / Lambda: Use the service's NAT gateway IP
- Local development: Leave the allowlist empty (all IPs allowed)
Agent Capability Grants
Beyond scopes (which control API-level access), capability grants provide data-level access controls for agents:
Table Allowlists
Restrict an agent to specific tables:
{
"agent_id": "analyst-01",
"capabilities": {
"allowed_tables": ["customers", "orders", "products"],
"denied_tables": ["internal_metrics", "employee_data"]
}
}
The agent can only query tables in allowed_tables. Any attempt to access other tables returns an authorization error.
Query Count Limits
Set per-agent query quotas:
{
"agent_id": "analyst-01",
"capabilities": {
"max_queries_per_hour": 1000,
"max_queries_per_day": 10000
}
}
When the limit is reached, subsequent queries are rejected until the window resets.
Expiration
Agent capability grants can have independent expiration from the API key:
{
"agent_id": "contractor-agent",
"capabilities": {
"allowed_tables": ["public_data"],
"expires_at": "2025-02-01T00:00:00Z"
}
}
This is useful for time-bounded access (e.g., a contractor agent that should only have access for one month).
Agent Identification
When an agent connects to HatiData, it identifies itself through PostgreSQL startup parameters:
| Parameter | Description | Example |
|---|---|---|
agent_id | Unique agent identifier | "langchain-prod-01" |
framework | Agent framework name | "langchain", "crewai", "autogen", "custom" |
These parameters are set automatically by HatiData's SDK and integration packages:
# Using the Python SDK
agent = HatiDataAgent(
host="your-org.proxy.hatidata.com",
agent_id="my-agent", # Sent as startup parameter
framework="langchain", # Sent as startup parameter
password="hd_live_your_key", # Used for authentication
)
The proxy extracts these parameters on connection and uses them throughout the query pipeline for:
- Audit logging -- Every query includes the
agent_idandframeworkin the audit record - Policy evaluation -- ABAC rules can match on
agent_idorframework(e.g., "allow only langchain agents to query the ML training data table") - Row-level security -- RLS WHERE clauses can use
{agent_id}and{agent_framework}placeholders - Billing -- Credits are tracked per agent, enabling cost allocation to specific agents or teams
Per-Agent Billing and Metering
Every query executed by an agent is metered and attributed to the agent's identity:
-- View per-agent costs (query the audit log directly)
SELECT
agent_id,
framework,
COUNT(*) as query_count,
SUM(credits_used) as total_credits,
AVG(duration_ms) as avg_latency_ms
FROM _hatidata_audit_log
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY agent_id, framework
ORDER BY total_credits DESC;
Credit Tracking
Each query's credit cost is computed by the proxy's cost estimation step:
| Factor | Credit Weight |
|---|---|
| Base query | 1 credit |
| Per table scanned | +0.5 credits |
| Full table scan (no WHERE) | +2 credits |
SELECT * (all columns) | +1 credit |
| Result set > 10,000 rows | +1 credit per 10K rows |
Quota Enforcement
Per-organization credit limits are set in the control plane:
{
"org_id": "org_abc123",
"monthly_credit_limit": 100000,
"alert_threshold_pct": 80
}
When an agent's query would exceed the organization's remaining credits, the query is rejected with a descriptive error message.
Audit Trail
Every API key usage is logged in the audit trail with full context:
{
"event_type": "query_executed",
"agent_id": "langchain-prod-01",
"framework": "langchain",
"key_id": "key_abc123",
"source_ip": "10.0.1.100",
"sql": "SELECT customer_id, SUM(total) FROM orders GROUP BY 1",
"tables_accessed": ["orders"],
"credits_used": 1.5,
"duration_ms": 42,
"timestamp": "2025-01-15T10:30:00Z"
}
The audit log is immutable (append-only) and can be queried through the dashboard or directly via SQL.
Best Practices
Key Rotation
- Rotate production keys every 90 days
- Use the API to create a new key, update agent configurations, then revoke the old key
- Test keys do not need rotation
Scope Minimization
- Grant the minimum scopes needed for the agent's task
- Read-only agents should use the
read_onlybundle - Avoid giving agents
adminorkeys:managescopes
Agent Identity
- Use descriptive, unique
agent_idvalues (e.g.,"langchain-revenue-analyst-prod") - Include the environment in the agent ID to distinguish dev/staging/prod
- Set the
frameworkparameter accurately for proper audit attribution
IP Restrictions
- Always set IP allowlists for production keys
- Use CIDR ranges for dynamic environments (Kubernetes, auto-scaling groups)
- Leave allowlists empty only for development/testing
Next Steps
- Security Overview -- RBAC, ABAC, and the full security model
- Agent Memory -- Persistent agent state and memory
- Agent Integrations -- Framework-specific integration guides