Advanced Configuration
Master custom tool creation, prompt engineering techniques, resource management, plugin extensions, and environment variable configuration.
Custom Tools
Tools are the hands of your agents β they allow agents to interact with the outside world. ThePopeBot comes with built-in tools, but you can create custom tools for any purpose.
Creating a Custom Tool
Every tool implements the Tool interface:
import { defineTool, ToolResult } from '../engine/tools';
export const databaseTool = defineTool({
name: 'database',
description: 'Query and manipulate the application database',
parameters: {
action: {
type: 'string',
enum: ['query', 'insert', 'update'],
description: 'The database operation to perform',
},
table: {
type: 'string',
description: 'The target table name',
},
data: {
type: 'object',
description: 'The query parameters or data payload',
},
},
required: ['action', 'table'],
async execute(params): Promise<ToolResult> {
const { action, table, data } = params;
switch (action) {
case 'query':
const results = await db.select(table, data);
return { success: true, data: results };
case 'insert':
const id = await db.insert(table, data);
return { success: true, data: { id } };
case 'update':
const count = await db.update(table, data);
return { success: true, data: { updatedRows: count } };
default:
return { success: false, error: `Unknown action: ${action}` };
}
},
});
Registering the Tool
Add it to config/tools.yaml:
tools:
database:
module: "./tools/database"
enabled: true
permissions:
- query
- insert
- update
rateLimit:
maxCalls: 100
windowMs: 60000
Tool Safety
Always implement safety measures in your custom tools:
async execute(params): Promise<ToolResult> {
// Validate inputs
if (!allowedTables.includes(params.table)) {
return { success: false, error: 'Access denied to this table' };
}
// Sanitize data
const sanitized = sanitize(params.data);
// Log the operation
logger.info('Tool execution', { tool: 'database', params: sanitized });
// Execute with timeout
return withTimeout(5000, () => db.query(sanitized));
}
Prompt Engineering Techniques
The quality of your agent depends heavily on its system prompt. Here are advanced techniques for crafting effective prompts.
Chain of Thought (CoT)
Instruct the agent to think step by step before acting:
When solving a problem:
1. First, restate the problem in your own words
2. List the key constraints and requirements
3. Consider 2-3 possible approaches
4. Evaluate each approach against the constraints
5. Choose the best approach and explain why
6. Implement the solution
7. Verify the solution meets all requirements
Few-Shot Examples
Provide examples of expected input-output pairs:
Example 1:
Input: "Add a password reset endpoint"
Plan:
- Create POST /api/auth/reset-password
- Generate a time-limited reset token
- Send reset email with token link
- Create PUT /api/auth/reset-password/:token to set new password
Output: [implementation files]
Example 2:
Input: "Fix the login timeout issue"
Plan:
- Investigate current timeout settings
- Check session middleware configuration
- Identify the root cause
- Apply fix with proper error handling
Output: [fix details]
Structured Output Format
Define the exact format you want the agent to produce:
Always respond with this structure:
## Analysis
[Brief analysis of the task]
## Plan
1. [Step 1]
2. [Step 2]
...
## Implementation
[Code or actions taken]
## Verification
[How you verified the solution works]
## Next Steps
[Suggestions for follow-up work]
Persona Layering
Combine multiple perspectives into a single prompt:
You are a senior developer with three areas of expertise:
- As an architect, you consider system-wide impacts
- As a security engineer, you identify vulnerabilities
- As a performance engineer, you optimize for speed
When reviewing code, apply all three perspectives and
clearly label which perspective each finding comes from.
Resource Limits
Production agents need resource constraints to prevent runaway costs and ensure fair usage.
Configuring Limits
Set limits in config/resources.yaml:
resources:
global:
maxConcurrentAgents: 10
maxTokensPerMinute: 100000
maxToolCallsPerRequest: 50
perAgent:
default:
maxTokensPerRequest: 4096
maxToolCalls: 20
timeoutMs: 120000 # 2 minutes
maxRetries: 3
coder:
maxTokensPerRequest: 8192
maxToolCalls: 50
timeoutMs: 300000 # 5 minutes
perUser:
maxRequestsPerHour: 60
maxTokensPerDay: 500000
Implementing Graceful Degradation
When limits are reached, agents should degrade gracefully:
const resourcePolicy = {
onTokenLimit: 'summarize', // Summarize instead of truncating
onToolLimit: 'prioritize', // Execute only high-priority tools
onTimeout: 'partial-result', // Return what's done so far
onRateLimit: 'queue', // Queue the request for later
};
Plugin Extensions
ThePopeBot supports a plugin system for extending functionality without modifying core code.
Plugin Structure
plugins/
βββ my-plugin/
β βββ index.ts # Plugin entry point
β βββ tools/ # Custom tools
β βββ agents/ # Custom agents
β βββ hooks/ # Lifecycle hooks
β βββ plugin.yaml # Plugin configuration
Creating a Plugin
import { definePlugin } from '../engine/plugins';
export default definePlugin({
name: 'github-integration',
version: '1.0.0',
description: 'Deep GitHub integration with issue tracking and CI/CD',
tools: [
githubIssueTool,
githubActionsTool,
githubProjectsTool,
],
hooks: {
onEvent: async (event) => {
// Pre-process events before they reach agents
if (event.source === 'webhook:github') {
event.metadata.enriched = await enrichGitHubData(event);
}
},
onResponse: async (response) => {
// Post-process agent responses
if (response.metadata.createIssue) {
await createGitHubIssue(response);
}
},
},
});
Plugin Configuration
# plugin.yaml
name: github-integration
enabled: true
config:
githubToken: "${GITHUB_TOKEN}"
defaultOrg: "my-org"
features:
autoLabel: true
ciIntegration: true
projectBoard: true
Environment Variables
ThePopeBot uses environment variables for sensitive configuration. Here is a comprehensive reference:
Core Variables
# LLM Provider
OPENAI_API_KEY=sk-...
OPENAI_ORG_ID=org-...
ANTHROPIC_API_KEY=sk-ant-...
LLM_PROVIDER=openai # openai, anthropic, or custom
# Server
PORT=3000
HOST=0.0.0.0
NODE_ENV=development # development, staging, production
# Logging
LOG_LEVEL=info # debug, info, warn, error
LOG_FORMAT=json # json or pretty
Channel Variables
# Telegram
TELEGRAM_BOT_TOKEN=...
TELEGRAM_ALLOWED_USERS=...
# Webhooks
GITHUB_WEBHOOK_SECRET=...
WEBHOOK_BASE_URL=https://your-domain.com
Security Variables
# Authentication
JWT_SECRET=your-secret-key
SESSION_TIMEOUT=3600
CORS_ORIGINS=https://your-domain.com
# Encryption
ENCRYPTION_KEY=...
ENCRYPTION_ALGORITHM=aes-256-gcm
Best Practices for Environment Variables
- Never commit
.envfiles to version control - Use
.env.exampleas a template with placeholder values - Validate on startup β fail fast if required variables are missing
- Use different values for development, staging, and production
- Rotate secrets regularly, especially API keys and JWT secrets
// Startup validation example
const required = ['OPENAI_API_KEY', 'JWT_SECRET', 'LLM_PROVIDER'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
}