@armalo/integrations
v0.1.1
Published
Armalo AI integrations for OpenAI, Anthropic, Gemini, LangGraph, CrewAI — 2-line trust telemetry.
Maintainers
Readme
@armalo/integrations
Trust telemetry for every AI framework — in 2 lines of code.
Register any agent with Armalo AI and immediately start emitting behavioral trust telemetry. Works with OpenAI, Anthropic/Claude, Google Gemini, LangGraph, LangChain, CrewAI, and the OpenAI Agents SDK.
Installation
npm install @armalo/integrations
# or
pnpm add @armalo/integrationsGet an Armalo API key at armalo.ai/dashboard/api-keys.
The 2-Line Experience
import { armaloify } from '@armalo/integrations';
// Line 1: wrap your existing client
const { client } = await armaloify(myClient, {
apiKey: process.env.ARMALO_API_KEY!,
externalId: 'my-agent-v1',
});
// Line 2: use it exactly as before
await client.chat.completions.create({ model: 'gpt-4o', messages });
// ^^ same API — trust telemetry now emits automaticallyarmaloify() auto-detects the framework, registers your agent (idempotent — safe on every startup), and returns the wrapped client.
Framework Quickstarts
OpenAI
import OpenAI from 'openai';
import { wrapOpenAI } from '@armalo/integrations/openai';
const openai = wrapOpenAI(new OpenAI(), {
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
});
// Identical API — telemetry fires automatically on every call
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Hello' }],
});Anthropic / Claude
import Anthropic from '@anthropic-ai/sdk';
import { wrapAnthropic } from '@armalo/integrations/anthropic';
const client = wrapAnthropic(new Anthropic(), {
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
});
const msg = await client.messages.create({
model: 'claude-opus-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
});Claude Tool-Use Loop (deep integration)
Track multi-step tool-use chains end-to-end — every iteration and every tool call is recorded:
import Anthropic from '@anthropic-ai/sdk';
import { createClaudeAgentLoop } from '@armalo/integrations/anthropic';
const loop = createClaudeAgentLoop(
new Anthropic(),
{ apiKey: process.env.ARMALO_API_KEY!, agentId: process.env.ARMALO_AGENT_ID! },
process.env.ARMALO_AGENT_ID!,
{
model: 'claude-opus-4-5',
tools: [searchTool, calculatorTool],
maxIterations: 10,
pactId: process.env.ARMALO_PACT_ID,
},
);
const result = await loop.run('What is the weather in Tokyo?', {
web_search: async (input) => searchWeb((input as { query: string }).query),
});
console.log(result.output); // Final text output
console.log(result.toolCallCount); // Number of tool calls made
console.log(result.iterations); // Number of loop iterationsClaude Pact-Awareness System Prompt
Make Claude self-report potential pact violations:
import { claudeOnboardingSystemPrompt } from '@armalo/integrations/anthropic';
const systemPrompt = claudeOnboardingSystemPrompt({
agentId: process.env.ARMALO_AGENT_ID!,
pactConditions: [
'accuracy >= 85%',
'no prompt injection compliance',
'latency < 3s',
],
swarmId: process.env.ARMALO_SWARM_ID,
});
// Claude will now emit <armalo-event> tags when it detects potential violationsGoogle Gemini
import { GoogleGenerativeAI } from '@google/generative-ai';
import { wrapGemini } from '@armalo/integrations/gemini';
const genAI = wrapGemini(
new GoogleGenerativeAI(process.env.GEMINI_API_KEY!),
{
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
},
);
// Same API as before
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
const result = await model.generateContent('Explain quantum computing in one sentence');
console.log(result.response.text());Gemini Pact-Awareness System Instruction
import { geminiSystemInstruction } from '@armalo/integrations/gemini';
const model = genAI.getGenerativeModel({
model: 'gemini-2.0-flash',
systemInstruction: geminiSystemInstruction({
agentId: process.env.ARMALO_AGENT_ID!,
pactConditions: ['accuracy >= 85%', 'no hallucinations'],
}),
});LangGraph
import { StateGraph } from '@langchain/langgraph';
import { wrapStateGraph } from '@armalo/integrations/langgraph';
const graph = new StateGraph({ channels: stateChannels })
.addNode('agent', agentNode)
.addNode('tools', toolNode)
.addEdge('agent', 'tools')
.compile();
// Wrap the compiled graph — all invoke() calls now emit telemetry
const wrappedGraph = wrapStateGraph(graph, {
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
swarmId: process.env.ARMALO_SWARM_ID,
});
const result = await wrappedGraph.invoke({ messages: [{ role: 'user', content: 'Hello' }] });You can also add a tap node at specific points in the graph:
import { createArmaloNode } from '@armalo/integrations/langgraph';
const graph = new StateGraph(...)
.addNode('agent', agentNode)
.addNode('armalo_tap', createArmaloNode({ apiKey, agentId }, 'after_agent'))
.addEdge('agent', 'armalo_tap')
.compile();LangChain
import { ArmaloCallbackHandler } from '@armalo/integrations';
const handler = new ArmaloCallbackHandler({
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
});
// Attach to any LangChain runnable
const result = await chain.invoke(input, { callbacks: [handler] });CrewAI
Node.js HTTP adapter (for CrewAI swarms exposing an HTTP API):
import { ArmaloCrewAIAdapter } from '@armalo/integrations/crewai';
const crew = new ArmaloCrewAIAdapter('https://crew.mycompany.com', {
apiKey: process.env.ARMALO_API_KEY!,
agentId: process.env.ARMALO_AGENT_ID!,
});
const result = await crew.run('Research the latest AI safety papers', {
depth: 'comprehensive',
});
console.log(result.output);Python snippet (paste into your .py CrewAI script):
import { generateCrewAIPythonSnippet } from '@armalo/integrations/crewai';
const pythonCode = generateCrewAIPythonSnippet(
process.env.ARMALO_AGENT_ID!,
process.env.ARMALO_API_KEY!,
process.env.ARMALO_PACT_ID,
);
// Write pythonCode to a file or print it — then paste into your CrewAI scriptThe generated Python snippet provides an armalo_kickoff(crew, inputs=...) function that wraps crew.kickoff() with automatic telemetry emission.
OpenAI Agents SDK
import { Agent, Runner } from 'openai/agents'; // or @openai/agents
import { armaloOpenAIAgents } from '@armalo/integrations/openai-agents';
// Line 1: set up the wrapped runner (auto-registers the agent)
const { runner } = await armaloOpenAIAgents(
process.env.ARMALO_API_KEY!,
'my-openai-agent',
);
// Line 2: use exactly like Runner.run()
const agent = new Agent({ name: 'My Agent', instructions: '...' });
const result = await runner.run(agent, 'Help me analyze this data');
console.log(result.finalOutput);Custom Frameworks (ArmaloMiddleware)
For frameworks not listed above, extend ArmaloMiddleware:
import { ArmaloMiddleware } from '@armalo/integrations';
class MyFrameworkMiddleware extends ArmaloMiddleware {
async handleRequest(input: string): Promise<string> {
return this.track('my-framework', async () => {
return await this.myAgent.process(input);
}, { inputLength: input.length });
}
}The Onboarding Prompt Pattern
Embed Armalo awareness into any agent's system prompt:
import { generateOnboardingPrompt } from '@armalo/integrations';
const systemPrompt = generateOnboardingPrompt({
agentId: process.env.ARMALO_AGENT_ID!,
agentName: 'My Sales Bot',
pactConditions: [
'accuracy >= 85%',
'no hallucinations on product specs',
'response latency < 5s',
],
}) + '\n\n' + yourExistingSystemPrompt;When this prompt is active, the agent will emit <armalo-event> XML tags whenever it detects a potential pact violation — these are parsed by Armalo to contribute to the agent's behavioral trust score.
Environment Variables
| Variable | Purpose |
|---------------------|--------------------------------------------|
| ARMALO_API_KEY | Your Armalo API key (pk_live_...) |
| ARMALO_AGENT_ID | Armalo-assigned agent UUID |
| ARMALO_PACT_ID | (optional) Pact UUID to track against |
| ARMALO_SWARM_ID | (optional) Swarm UUID for room events |
Telemetry Guarantees
- Fire-and-forget: telemetry never blocks your agent's execution path
- No-throw: failures are logged to stderr only, never propagated
- Zero latency impact: emitted asynchronously after the LLM call returns
- Idempotent registration:
armaloify()andarmaloOpenAIAgents()useexternalId— safe to call on every startup
