AI Agent Integration
Integrate Elydora into your AI agent workflows to create cryptographically signed, tamper-evident records of every autonomous action.
Why AI Agents Need Accountability
Autonomous AI agents make decisions and take actions without direct human oversight. In regulated industries such as finance, healthcare, and insurance, every agent action must be auditable. Elydora records each action as a signed Elydora Operation Record (EOR) that proves what the agent did, when it did it, and that the record has not been altered.
Supported AI Coding Tools
Elydora provides one-command installation for AI coding tools. The CLI installs a self-contained hook script that records every tool use as a signed EOR without code changes.
One-Command Install
After registering an agent in the Elydora Console, run a single CLI command to configure your tool. The command carries public identifiers, writes a self-contained hook script, and registers it with your tool's hook system. The CLI requests the private key and optional API token through echo-disabled prompts. Choose your SDK:
npx @elydora/sdk install --agent claudecode \
--org_id "your_org_id" --agent_id "your_agent_id" \
--kid "your_key_id" --base_url "https://api.elydora.com"python -m pip install elydora
elydora install --agent claudecode \
--org_id "your_org_id" --agent_id "your_agent_id" \
--kid "your_key_id" --base_url "https://api.elydora.com"go install github.com/Elydora-Infrastructure/Elydora-Go-SDK/v2/cmd/elydora@latest
elydora install --agent claudecode \
--org-id "your_org_id" --agent-id "your_agent_id" \
--kid "your_key_id" --base-url "https://api.elydora.com"Replace claudecode with the agent flag for your tool: augment, claudecode, cline, codex, copilot, cursor, droid, gemini, grok, kimi, kirocli, kiroide, letta, opencode, or qwen. Enterprise, GUI, SDK-managed, and other agents connect directly through an SDK.
The console pre-fills the agent identity and API URL. Copy each secret with its explicit control and enter it only when the CLI prompts.
Automation with Secret Files
For non-interactive automation, store each secret in a file readable only by its owner, then pass the file path. Secret values stay out of process arguments.
npx @elydora/sdk install --agent claudecode \
--org_id "your_org_id" --agent_id "your_agent_id" \
--kid "your_key_id" --base_url "https://api.elydora.com" \
--private_key_file "/secure/path/private.key" \
--token_file "/secure/path/api.token"python -m pip install elydora
elydora install --agent claudecode \
--org_id "your_org_id" --agent_id "your_agent_id" \
--kid "your_key_id" --base_url "https://api.elydora.com" \
--private_key_file "/secure/path/private.key" \
--token_file "/secure/path/api.token"go install github.com/Elydora-Infrastructure/Elydora-Go-SDK/v2/cmd/elydora@latest
elydora install --agent claudecode \
--org-id "your_org_id" --agent-id "your_agent_id" \
--kid "your_key_id" --base-url "https://api.elydora.com" \
--private-key-file "/secure/path/private.key" \
--token-file "/secure/path/api.token"How It Works
The install command creates a per-agent directory at ~/.elydora/{agentId}/ and configures the following:
- Hook script (hook.js / hook.py) — A PostToolUse hook that fires after each tool call. Embeds all cryptographic logic (Ed25519 signing, SHA-256 hashing, chain hash computation) with zero runtime dependencies
- Guard script (guard.js / guard.py) — A PreToolUse hook that enforces agent freeze status. When an agent is frozen via the console, the guard rejects tool calls before they execute, preventing further autonomous actions until the freeze is lifted
- Agent config — Credentials stored at ~/.elydora/{agentId}/config.json with the Ed25519 private key in a separate private.key file (chmod 600)
- Chain state (chain-state.json) — Persists the most recent chain hash for this agent, ensuring each new EOR links to the previous one even across process restarts
- Tool registration — The hook and guard are registered in your tool's configuration (e.g. ~/.claude/settings.json for Claude Code)
- Fire-and-forget — The hook always exits 0. Audit logging never blocks your workflow. Errors are logged to ~/.elydora/{agentId}/error.log
Per-Agent Directory Structure
Each agent gets its own isolated directory under ~/.elydora/:
~/.elydora/{agentId}/
├── config.json # org_id, agent_id, kid, base_url, agent_name, token
├── private.key # Ed25519 private key (chmod 600)
├── hook.js/.py # PostToolUse audit logging hook
├── guard.js/.py # PreToolUse freeze enforcement hook
├── chain-state.json # Per-agent chain hash persistence
├── status-cache.json # Freeze status cache (60s TTL)
└── error.log # Per-agent error logCross-Platform Paths
On macOS and Linux, the base directory is ~/.elydora/. On Windows, the SDK uses the user profile directory:
$env:USERPROFILE\.elydora\{agentId}\%USERPROFILE%\.elydora\{agentId}\The CLI resolves the base path for the current platform. No path configuration is needed.
CLI Commands
# Remove the hook and clean up config
elydora uninstall --agent <name>
# Show installation status for all agents
elydora status
# List all supported agent names
elydora agentsSDK Integration
For custom enterprise, GUI-based, SDK-managed, and other agents, integrate Elydora directly in your code using the SDK. The console provides public identifiers, explicit secret copy controls, and a tutorial that reads secrets from runtime environment variables.
Step 1: Install the SDK
# Node.js
npm install @elydora/sdk
# Python
pip install elydora
# Go
go get github.com/Elydora-Infrastructure/Elydora-Go-SDK/v2Step 2: Initialize the Client
Create a client with the credentials from your agent registration. Store the private key and token in environment variables and keep them out of source control.
import { ElydoraClient } from '@elydora/sdk';
const client = new ElydoraClient({
orgId: process.env.ELYDORA_ORG_ID,
agentId: process.env.ELYDORA_AGENT_ID,
privateKey: process.env.ELYDORA_PRIVATE_KEY,
kid: process.env.ELYDORA_KID,
});
client.setToken(process.env.ELYDORA_TOKEN);import os
from elydora import ElydoraClient
client = ElydoraClient(
org_id=os.environ["ELYDORA_ORG_ID"],
agent_id=os.environ["ELYDORA_AGENT_ID"],
private_key=os.environ["ELYDORA_PRIVATE_KEY"],
token=os.environ["ELYDORA_TOKEN"],
)
client.set_kid(os.environ["ELYDORA_KID"])import (
"os"
elydora "github.com/Elydora-Infrastructure/Elydora-Go-SDK/v2"
)
client, err := elydora.NewClient(&elydora.Config{
OrgID: os.Getenv("ELYDORA_ORG_ID"),
AgentID: os.Getenv("ELYDORA_AGENT_ID"),
PrivateKey: os.Getenv("ELYDORA_PRIVATE_KEY"),
Token: os.Getenv("ELYDORA_TOKEN"),
})Step 3: Record Operations
Before or after each tool call, decision, or action your agent takes, create a tamper-evident operation record (EOR).
const eor = client.createOperation({
operationType: 'ai.tool_use',
subject: { type: 'user', id: 'user-123' },
action: { tool: 'web_search', query: 'quarterly revenue' },
payload: { result: 'approved', confidence: 0.97 },
});
const { receipt } = await client.submitOperation(eor);
console.log('Recorded:', receipt.operation_id, 'seq:', receipt.seq_no);Step 4: Verify (Optional)
const result = await client.verifyOperation(receipt.operation_id);
console.log('Signature:', result.checks.signature); // true
console.log('Chain:', result.checks.chain); // trueIntegration Pattern
Wrap each agent action in an Elydora operation. Before the agent executes an action, create and submit a signed EOR. After Elydora returns an Elydora Acknowledgement Receipt (EAR), proceed with execution.
while agent is running:
action = agent.decide_next_action()
// 1. Create a signed EOR for the action
eor = elydora.create_operation(
operation_type: action.type,
subject: action.target,
action: action.name,
payload: action.parameters
)
// 2. Submit the EOR to Elydora
ear = elydora.submit_operation(eor)
// 3. Execute the action only after receiving the receipt
result = agent.execute(action)
// 4. Optionally verify the record
verification = elydora.verify_operation(ear.operation_id)Example: LLM Tool-Calling Agent
In an LLM agent that uses tool calling, each tool invocation is one unit of accountability. Log every tool call as an Elydora operation before executing it.
import { ElydoraClient } from '@elydora/sdk';
const client = new ElydoraClient({
orgId: 'org_acme',
agentId: 'agent_assistant',
privateKey: process.env.ELYDORA_KEY,
});
async function handleToolCall(toolName: string, args: Record<string, unknown>) {
// Create and submit a signed operation record before executing
const record = client.createOperation({
operationType: `tool.${toolName}`,
subject: { type: 'tool', id: toolName },
action: { name: 'invoke', type: 'tool_use' },
payload: { tool: toolName, arguments: args },
});
const { receipt } = await client.submitOperation(record);
// receipt contains the EAR with receipt_id, seq_no, chain_hash
// Now execute the tool call
const result = await executeTool(toolName, args);
return { result, operationId: receipt.operation_id };
}Raw API Equivalent
The SDK constructs a full EOR and sends it to POST /v1/operations. The raw request:
curl -X POST https://api.elydora.com/v1/operations \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"op_version": "1.0",
"operation_id": "0195f2c7-1b3c-7d5e-8f2a-4b6c8d0e2f3a",
"org_id": "org_acme",
"agent_id": "agent_assistant",
"issued_at": 1772289000000,
"ttl_ms": 30000,
"nonce": "x9k2m4p7q1w3vB7n",
"operation_type": "tool.search_database",
"subject": { "type": "database", "id": "customer_records" },
"action": { "name": "search", "type": "query" },
"payload": {
"tool": "search_database",
"arguments": { "query": "overdue accounts", "limit": 50 }
},
"payload_hash": "<base64url SHA-256 of the canonical payload>",
"prev_chain_hash": "<base64url chain hash of the previous operation>",
"agent_pubkey_kid": "agent_assistant-key-1",
"signature": "<base64url Ed25519 signature>"
}'Example: Multi-Agent System
In a multi-agent architecture, each agent has its own Ed25519 key pair and its own chain of operations. Register each agent separately, then instantiate a client per agent.
import { ElydoraClient } from '@elydora/sdk';
// Each agent gets its own client with its own key pair
const researchAgent = new ElydoraClient({
orgId: 'org_acme',
agentId: 'agent_researcher',
privateKey: process.env.RESEARCHER_KEY,
});
const reviewAgent = new ElydoraClient({
orgId: 'org_acme',
agentId: 'agent_reviewer',
privateKey: process.env.REVIEWER_KEY,
});
// Agent 1: Research agent finds and summarizes data
const summaryData = { revenueGrowth: 0.12, sources: 4 };
const researchRecord = researchAgent.createOperation({
operationType: 'research.summarize',
subject: { type: 'dataset', id: 'quarterly_reports' },
action: { name: 'summarize', type: 'analysis' },
payload: { source: 'quarterly_reports', findings: summaryData },
});
const { receipt: researchReceipt } = await researchAgent.submitOperation(researchRecord);
// Agent 2: Review agent evaluates the research
const reviewRecord = reviewAgent.createOperation({
operationType: 'review.evaluate',
subject: { type: 'operation', id: researchReceipt.operation_id },
action: { name: 'evaluate', type: 'review' },
payload: {
sourceOperationId: researchReceipt.operation_id,
decision: 'approved',
notes: 'Findings consistent with source data',
},
});
const { receipt: reviewReceipt } = await reviewAgent.submitOperation(reviewRecord);Registering Multiple Agents
Before agents can submit operations, register each one with its Ed25519 public key via POST /v1/agents/register.
# Register the research agent
curl -X POST https://api.elydora.com/v1/agents/register \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_researcher",
"display_name": "Research Agent v1",
"integration_type": "sdk",
"keys": [{ "kid": "agent_researcher-key-1", "public_key": "<base64url public key>", "algorithm": "ed25519" }]
}'
# Register the review agent
curl -X POST https://api.elydora.com/v1/agents/register \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_reviewer",
"display_name": "Review Agent v1",
"integration_type": "sdk",
"keys": [{ "kid": "agent_reviewer-key-1", "public_key": "<base64url public key>", "algorithm": "ed25519" }]
}'EOR Field Reference
Every EOR submitted to Elydora contains these fields. The SDK auto-generates operation_id, issued_at, nonce, payload_hash, prev_chain_hash, and signature.
- op_version — Protocol version, currently "1.0"
- operation_id — Client-generated UUIDv7
- org_id — Your organization identifier
- agent_id — The agent performing the action
- issued_at — Unix timestamp in milliseconds
- ttl_ms — Maximum submission window in milliseconds
- nonce — Random value for replay protection
- operation_type — Domain-specific type (e.g. tool.search_database)
- subject — The entity or resource acted upon
- action — The action performed (e.g. search, approve)
- payload — Arbitrary JSON with operation-specific data
- payload_hash — Base64url SHA-256 of the canonical payload
- prev_chain_hash — Chain hash of the agent's previous operation; the genesis constant for the first operation
- agent_pubkey_kid — Key ID of the agent's Ed25519 signing key
- signature — Ed25519 signature over the canonical EOR
Next Steps
- Follow the Getting Started guide for a complete end-to-end walkthrough
- Read the EOR specification for full field semantics and canonical form rules
- Browse the Operations API for all available endpoints
- Set up RBAC roles to control which agents and users can perform which actions