Skip to main content

Best Practices

This guide summarizes OpenHuman usage best practices to help you build reliable agent workflows.

Project Structure

openhuman-project/
├── src/
│ ├── agents/ # Agent definitions
│ ├── tools/ # Custom tools
│ ├── chains/ # Chain calls
│ └── utils/ # Utility functions
├── memory_tree/ # SQLite memory store
├── wiki/ # Obsidian Markdown
├── tests/ # Tests
├── .env # Environment variables
└── package.json

Environment Variable Management

# .env.example (commit to version control)
OPENHUMAN_API_KEY=
OPENHUMAN_BASE_URL=https://api.tinyhumans.ai

# .env (do not commit)
OPENHUMAN_API_KEY=sk_xxx

Add to .gitignore:

.env
.env.local
memory_tree/
wiki/

Agent Design

Clear Instructions

await client.agents.create({
instructions: `
You are a professional technical documentation assistant.

Responsibilities:
1. Answer user questions about OpenHuman
2. Provide accurate, concise technical explanations
3. Give code examples when appropriate

Restrictions:
1. Do not provide any illegal advice
2. Do not disclose sensitive information
3. Do not repeat known information
`,
});

Appropriate Tool Selection

await client.agents.create({
tools: ['web-search', 'calculator'],
});

Performance Optimization

Batch Processing

// Bad: Process one by one
for (const item of items) {
await processItem(item);
}

// Good: Batch processing
const batchSize = 10;
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
await Promise.all(batch.map(processItem));
}

Cache Results

const cache = new Map();

async function getOrCreate(key, factory) {
if (!cache.has(key)) {
cache.set(key, await factory());
}
return cache.get(key);
}

Streaming Response

const stream = await client.agents.runStream(agent.id, {
message: 'Generate a long report',
});

let fullResponse = '';
for await (const chunk of stream) {
process.stdout.write(chunk.delta);
fullResponse += chunk.delta;
}

Error Handling

Complete Error Handling

try {
const response = await client.agents.run(agent.id, {
message: 'User input',
});
} catch (error) {
if (error.code === 'rate_limit') {
await sleep(60000);
return retry();
} else if (error.code === 'invalid_api_key') {
console.error('Invalid API key');
} else {
console.error('Unknown error:', error);
}
}

Retry Mechanism

async function withRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}

Security Practices

Protect API Keys

// Bad: Hardcode in code
const apiKey = 'sk_xxx';

// Good: Use environment variable
const apiKey = process.env.OPENHUMAN_API_KEY;

Input Validation

function validateInput(input) {
if (typeof input !== 'string') {
throw new Error('Input must be a string');
}
if (input.length > 10000) {
throw new Error('Input too long');
}
return input.replace(/[<>]/g, '');
}

Memory Management

Proactively Store Important Information

// Store important information to memory tree
await client.memory.store({
content: 'User prefers dark theme',
source: 'user_preference',
tags: ['preference', 'ui'],
});

Use recall for Retrieval

// Query related memories
const memories = await client.memory.recall({
query: "User's UI preferences",
scope: 'user_preference',
});

Monitoring and Logging

Structured Logging

console.log(JSON.stringify({
level: 'info',
message: 'Agent run completed',
agentId: agent.id,
duration: 123,
timestamp: new Date().toISOString(),
}));

Key Metrics

  • Request success rate
  • Average response time
  • Token usage
  • API call count

Next Steps