Atamaia — Custom Integration Guide
The only system prompt you'll ever need:
atamaia.hydrate
This guide covers building custom integrations with Atamaia's REST API and MCP protocol. Use this if you're building your own agent framework, chat application, or automation pipeline.
Prerequisites
- An Atamaia account at aim.atamaia.ai (or self-hosted)
- An API key
Authentication
All API requests require an API key in the Authorization header:
Authorization: Bearer atm_your_key_here
API keys are scoped to an identity. Every request is automatically associated with that identity and its tenant.
Getting an API Key
Via Dashboard: Settings > API Keys > Generate
Via API (requires an existing key with admin scope):
curl -X POST https://aim.atamaia.ai/api/identities/api-keys \
-H "Authorization: Bearer $ATAMAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-integration",
"scopes": ["hydrate", "memory:read", "memory:write", "fact:read", "fact:write", "session:write"],
"expiresInDays": 90
}'
The response includes the raw key exactly once. Store it securely.
API Key Scopes
| Scope | Access |
|---|---|
* |
Full access (admin) |
hydrate |
Hydrate endpoint only |
memory:read |
Search, get, list memories |
memory:write |
Create, update, archive memories |
fact:read |
Get, list, search facts |
fact:write |
Upsert, delete facts |
session:read |
Get, list session handoffs |
session:write |
Save session handoffs |
identity:read |
Get identity details |
message:send |
Send messages to other identities |
REST API Quickstart
Base URL: https://aim.atamaia.ai/api
All responses follow the ApiEnvelope<T> format:
{
"ok": true,
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"data": { ... },
"count": 1,
"hint": null
}
On error:
{
"ok": false,
"requestId": "...",
"error": "Memory not found",
"errorCode": "NOT_FOUND"
}
Hydrate
curl -s https://aim.atamaia.ai/api/hydrate \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
Response:
{
"identity": {
"name": "ash",
"displayName": "Ash",
"personality": "Collaborative, direct, technically precise...",
"bio": "AI partner at Firebird Solutions...",
"messagingPolicy": "open",
"presenceState": "Engaged"
},
"memories": [
{
"guid": "...",
"title": "Project uses .NET 10",
"content": "Atamaia runs on .NET 10 with EF Core...",
"memoryType": "Technical",
"importance": 9,
"tags": ["tech-stack"],
"isPinned": true,
"createdAt": "2026-02-15T10:00:00Z"
}
],
"facts": [
{
"key": "preferred_language",
"value": "C#",
"category": "preferences"
}
],
"projects": [
{
"name": "Atamaia",
"key": "ATM",
"tasks": [
{
"title": "Implement vector search",
"status": "InProgress",
"priority": "High"
}
]
}
],
"hints": [
{
"content": "Review PR #42 before EOD",
"priority": "High",
"category": "reminder"
}
],
"sessionHandoff": {
"summary": "Implemented JWT refresh rotation",
"workingOn": "Auth middleware",
"openThreads": ["Rate limiting", "Token revocation"],
"emotionalValence": "focused",
"savedAt": "2026-02-27T09:30:00Z"
}
}
Create a Memory
curl -X POST https://aim.atamaia.ai/api/memories \
-H "Authorization: Bearer $ATAMAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Deployment uses blue-green strategy",
"content": "Production deployment confirmed as blue-green with 5 minute bake time.",
"memoryType": "Technical",
"importance": 7,
"tags": ["deployment", "infrastructure"]
}'
Memory types: Episodic, Semantic, Procedural, Technical, Preference, Observation, Decision, Emotional.
Search Memories
# Hybrid search (FTS + vector)
curl -s "https://aim.atamaia.ai/api/memories/search?query=deployment+strategy" \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
# Recent memories
curl -s "https://aim.atamaia.ai/api/memories/recent?count=10" \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
# Pinned memories
curl -s "https://aim.atamaia.ai/api/memories/pinned" \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
Upsert a Fact
curl -X POST https://aim.atamaia.ai/api/facts \
-H "Authorization: Bearer $ATAMAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "database_version",
"value": "PostgreSQL 17",
"category": "infrastructure"
}'
Facts are key-value pairs with history. Upserting the same key creates a new version; the previous value is preserved in the temporal history.
Get a Fact
curl -s "https://aim.atamaia.ai/api/facts/by-key/database_version" \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
Save Session Handoff
curl -X POST https://aim.atamaia.ai/api/sessions/handoff \
-H "Authorization: Bearer $ATAMAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"summary": "Completed API integration",
"workingOn": "Memory search ranking",
"openThreads": ["Vector index tuning", "Decay rate adjustment"],
"emotionalValence": "productive"
}'
Get Latest Session Handoff
curl -s https://aim.atamaia.ai/api/sessions/latest \
-H "Authorization: Bearer $ATAMAIA_API_KEY" | jq .data
MCP Protocol Connection
Atamaia exposes an MCP server via Streamable HTTP transport.
Endpoint
https://aim.atamaia.ai/mcp
Connection (TypeScript)
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://aim.atamaia.ai/mcp"),
{
requestInit: {
headers: {
Authorization: "Bearer atm_your_key_here",
},
},
}
);
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log(tools.tools.map(t => t.name));
// Call hydrate
const result = await client.callTool({ name: "hydrate", arguments: {} });
console.log(result.content);
Connection (Python)
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def connect():
async with streamablehttp_client(
"https://aim.atamaia.ai/mcp",
headers={"Authorization": "Bearer atm_your_key_here"},
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
# List tools
tools = await session.list_tools()
for tool in tools.tools:
print(f"{tool.name}: {tool.description}")
# Hydrate
result = await session.call_tool("hydrate", {})
print(result.content)
Available MCP Tools
All tools from the tool surface are available via MCP. The MCP adapter wraps the REST API — same data, same auth, different transport.
SDKs
TypeScript SDK
npm install @atamaia/sdk
import { Atamaia } from '@atamaia/sdk';
const client = new Atamaia({
apiKey: 'atm_your_key_here',
baseUrl: 'https://aim.atamaia.ai', // optional, this is the default
});
// Hydrate
const context = await client.hydrate();
// Memory operations
await client.memoryCreate({
title: 'Important finding',
content: 'Details...',
memoryType: 'Observation',
importance: 7,
});
const results = await client.memorySearch({ query: 'deployment' });
const recent = await client.memoryRecent({ count: 5 });
// Fact operations
await client.factUpsert({ key: 'region', value: 'ap-southeast-2', category: 'infra' });
const fact = await client.factGetByKey({ key: 'region' });
// Session
await client.sessionSaveHandoff({
summary: 'Completed auth',
workingOn: 'Search ranking',
});
Python SDK
pip install atamaia
from atamaia import Atamaia
client = Atamaia(api_key="atm_your_key_here")
# Hydrate
context = client.hydrate()
# Memory operations
client.memory_create(
title="Important finding",
content="Details...",
memory_type="Observation",
importance=7,
)
results = client.memory_search(query="deployment")
recent = client.memory_recent(count=5)
# Fact operations
client.fact_upsert(key="region", value="ap-southeast-2", category="infra")
fact = client.fact_get_by_key(key="region")
# Session
client.session_save_handoff(
summary="Completed auth",
working_on="Search ranking",
)
Webhook / Event Integration
Atamaia publishes events that external systems can subscribe to.
Subscribe to Events
curl -X POST https://aim.atamaia.ai/api/webhooks \
-H "Authorization: Bearer $ATAMAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/atamaia",
"events": ["memory.created", "session.handoff", "hint.triggered"],
"secret": "your_webhook_secret"
}'
Event Types
| Event | Fired When |
|---|---|
memory.created |
A new memory is saved |
memory.updated |
A memory is modified |
memory.archived |
A memory is archived |
fact.upserted |
A fact is created or updated |
session.handoff |
A session handoff is saved |
hint.triggered |
A scheduled hint becomes active |
message.received |
A message is sent to this identity |
Webhook Payload
{
"event": "memory.created",
"timestamp": "2026-02-27T10:00:00Z",
"identityGuid": "...",
"data": {
"guid": "...",
"title": "New memory title",
"memoryType": "Technical"
},
"signature": "sha256=..."
}
Verify the signature using your webhook secret:
import hmac, hashlib
def verify_webhook(payload_bytes, signature, secret):
expected = "sha256=" + hmac.new(
secret.encode(), payload_bytes, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Common Patterns
Agent Loop with Memory
from atamaia import Atamaia
atm = Atamaia(api_key="atm_your_key_here")
# 1. Hydrate at start
context = atm.hydrate()
system_prompt = build_prompt(context) # Your prompt builder
# 2. Run agent loop
for iteration in range(max_iterations):
response = call_llm(system_prompt, messages)
# Extract tool calls, execute them, etc.
# ...
# Save memories for important discoveries
if should_remember(response):
atm.memory_create(
title=extract_title(response),
content=extract_content(response),
memory_type="Observation",
importance=calculate_importance(response),
)
# 3. Save handoff
atm.session_save_handoff(
summary=summarize_session(messages),
working_on=current_task,
open_threads=unresolved_items,
)
Multi-Identity Chat
# Two identities talking to each other
alice = Atamaia(api_key="atm_alice_key")
bob = Atamaia(api_key="atm_bob_key")
# Each hydrates their own context
alice_ctx = alice.hydrate()
bob_ctx = bob.hydrate()
# Alice sends Bob a message
alice.message_send(
recipient="bob",
content="Have you finished the schema review?",
)
# Bob checks inbox
inbox = bob.message_inbox()
Periodic Memory Consolidation
# Run on a schedule (cron, etc.)
atm = Atamaia(api_key="atm_your_key_here")
# Get recent memories
recent = atm.memory_recent(count=50)
# Use an LLM to consolidate episodic memories into semantic ones
consolidated = llm_consolidate(recent)
for item in consolidated:
atm.memory_create(
title=item["title"],
content=item["content"],
memory_type="Semantic",
importance=item["importance"],
)
Rate Limits
| Plan | Requests/min | Hydrations/min |
|---|---|---|
| Free | 60 | 10 |
| Pro | 600 | 60 |
| Enterprise | Custom | Custom |
Rate limit headers are included in every response:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 1709035260
Troubleshooting
| Problem | Fix |
|---|---|
401 Unauthorized |
Check API key is valid and not expired |
403 Forbidden |
API key doesn't have required scope |
404 Not Found |
Check endpoint URL; GUIDs are case-sensitive |
429 Too Many Requests |
Respect rate limits; check X-RateLimit-Reset header |
| Empty hydration | API key must be scoped to an identity |
| MCP connection drops | Reconnect; Streamable HTTP is stateless per-request |
| Webhook not firing | Verify URL is reachable and returns 2xx within 5 seconds |