BRX Development Guide
This guide provides best practices and tips for developing applications with BRX. Whether you’re building a simple prototype or a complex production application, these guidelines will help you make the most of the BRX platform.
Development Environment Setup
Prerequisites
- Node.js 14+ (for using the Node.js SDK)
- A code editor (VS Code, WebStorm, etc.)
- A BRX account with API access
Local Development
For local development, you can use the BRX SDK with your development API key:
import BRX from 'brx-node';
// Use your development API key
const brx = new BRX('your-dev-api-key');
If you’re running a local instance of the BRX API (for internal development), you can configure the SDK to use it:
const brx = new BRX('your-api-key', {
send_local: true // Use local API endpoint
});
BRK Design Principles
Modularity
Design your BRKs to be modular and reusable. Each BRK should have a single responsibility and do it well.
✅ Good: Separate BRKs for data extraction, analysis, and report generation
❌ Bad: A single BRK that does everything
Always validate inputs to your BRKs to ensure they meet the expected format and constraints.
// Before executing a BRK, validate its inputs
if (!myBrk.input['data'] || typeof myBrk.input['data'] !== 'string') {
throw new Error('Data input must be a non-empty string');
}
Error Handling
Implement robust error handling in your applications to gracefully handle failures.
try {
const result = await brx.run(myBrk);
// Process the result
} catch (error) {
// Log the error
console.error('Error executing BRK:', error);
// Provide a user-friendly error message
if (error.message.includes('rate limit')) {
console.error('Rate limit exceeded. Please try again later.');
} else {
console.error('An error occurred. Please try again or contact support.');
}
}
Dependency Management
When creating BRKs with dependencies, be mindful of the dependency graph to avoid circular dependencies and excessive nesting.
✅ Good: A clear, directed acyclic graph of dependencies
❌ Bad: Circular dependencies or deeply nested dependencies
Minimize Token Usage
LLM-based operations consume tokens, which can impact performance and cost. Optimize your prompts to minimize token usage:
- Be concise and specific in your prompts
- Use shorter examples where possible
- Remove unnecessary context or instructions
Caching
Implement caching for BRK results that don’t change frequently:
const cache = new Map();
async function getCachedResult(brkId, inputs) {
const cacheKey = `${brkId}:${JSON.stringify(inputs)}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const brkSchema = await brx.get(brkId);
const myBrk = new BRK(brkSchema);
// Set inputs
Object.entries(inputs).forEach(([key, value]) => {
myBrk.input[key] = value;
});
const result = await brx.run(myBrk);
// Cache the result
cache.set(cacheKey, result);
return result;
}
Parallel Execution
For independent BRKs, you can execute them in parallel to improve performance:
// Execute multiple BRKs in parallel
const [result1, result2, result3] = await Promise.all([
brx.run(brk1),
brx.run(brk2),
brx.run(brk3)
]);
Testing
Unit Testing
Write unit tests for your BRK-related code to ensure it behaves as expected:
// Using Jest for testing
describe('Product Description Generator', () => {
let brx;
let productDescriptionBrk;
beforeAll(async () => {
brx = new BRX('test-api-key');
const schema = await brx.get('product-description-generator');
productDescriptionBrk = new BRK(schema);
});
test('generates a product description', async () => {
// Set inputs
productDescriptionBrk.input['product_name'] = 'Test Product';
productDescriptionBrk.input['product_category'] = 'Test Category';
productDescriptionBrk.input['key_features'] = 'Feature 1, Feature 2';
productDescriptionBrk.input['target_audience'] = 'Test Audience';
// Execute the BRK
const result = await brx.run(productDescriptionBrk);
// Assert on the result
expect(result).toBeDefined();
expect(result[0].brxRes.output).toContain('Test Product');
});
});
Mock Testing
For faster and more reliable tests, you can mock the BRX API responses:
// Mock the BRX client
jest.mock('brx-node', () => {
return {
__esModule: true,
default: jest.fn().mockImplementation(() => ({
get: jest.fn().mockResolvedValue({
// Mock schema
}),
run: jest.fn().mockResolvedValue([
{
brxId: 'test-brk',
brxName: 'Test BRK',
brxRes: {
output: 'Test output'
}
}
])
})),
BRK: jest.fn().mockImplementation(() => ({
input: {},
run: jest.fn().mockResolvedValue([
{
brxId: 'test-brk',
brxName: 'Test BRK',
brxRes: {
output: 'Test output'
}
}
])
}))
};
});
Deployment
Environment Variables
Store your API keys and other sensitive information in environment variables:
// Load environment variables
require('dotenv').config();
// Use environment variables
const brx = new BRX(process.env.BRX_API_KEY);
CI/CD Integration
Integrate BRX into your CI/CD pipeline to automate testing and deployment:
# Example GitHub Actions workflow
name: BRX CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm ci
- run: npm test
env:
BRX_API_KEY: ${{ secrets.BRX_API_KEY }}
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm ci
- run: npm run build
- name: Deploy
run: npm run deploy
env:
BRX_API_KEY: ${{ secrets.BRX_API_KEY }}
Production Considerations
When deploying to production, consider the following:
- Use a production API key with appropriate permissions
- Implement rate limiting and retry logic
- Monitor API usage and performance
- Set up alerts for errors and failures
- Implement proper error handling and fallbacks
Security Best Practices
API Key Management
- Never hardcode API keys in your code
- Use environment variables or a secure key management service
- Rotate API keys regularly
- Use different API keys for development and production
Sanitize user inputs before passing them to BRKs to prevent prompt injection and other security issues:
function sanitizeInput(input) {
// Remove potentially harmful characters or patterns
return input.replace(/[<>]/g, '');
}
// Before setting BRK inputs
myBrk.input['user_input'] = sanitizeInput(userInput);
Access Control
Use BRX’s access control features to restrict access to your BRKs:
// Update BRK access control
const updateAclRequest = {
brxId: 'your-brk-id',
isPublic: false,
isClone: false,
emails: [
{
email: 'user@example.com',
permission: 1 // Editor
}
]
};
await brx.update_brx_acl(updateAclRequest);
Monitoring and Debugging
Logging
Implement comprehensive logging to help debug issues:
// Enable verbose logging
const brx = new BRX('your-api-key', { verbose: true });
// Log BRK execution
console.log(`Executing BRK: ${myBrk.brxQuery.userSchemaInteract.mainBrxId}`);
const result = await brx.run(myBrk);
console.log(`BRK execution completed: ${result.length} results`);
Monitoring
Monitor your BRX usage and performance:
- Track API calls and response times
- Monitor token usage
- Set up alerts for errors and failures
- Analyze usage patterns to identify optimization opportunities
Further Resources
- BRX API Reference
- [Core Concepts: BRK](/docs/Core Concepts/BRK)
- [Core Concepts: BRX Client](/docs/Core Concepts/BRXClient)
- [Core Concepts: Composability](/docs/Core Concepts/Composability)
- [Core Concepts: Tool Calling](/docs/Core Concepts/ToolCalling)
- brx-node SDK Reference