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
- Troubleshooting - Problem solving
- API Documentation - API reference
- Privacy and Security - Data protection