Advanced

Paste this guide into Claude Code and it will walk you through every step interactively.

Building Jarvis: Multi-Agent System

What this gives you: Your own team of 7 AI specialists, each handling a different part of your business. One manages your LinkedIn. One handles YouTube. One does your accounting. One plans your strategy. They work independently, 24/7, and cost a fraction of hiring real people.

One AI that handles everything becomes slow, expensive, and confused. Seven specialist agents, each knowing exactly what it does, become something genuinely powerful.

The Problem With Single-Agent Systems

Most people build their AI assistant as one big monolith. One Claude instance, one system prompt, one context window that contains everything: your business context, your clients, your content strategy, your financials, your technical knowledge. Everything.

The problem is the context window becomes enormous. Every message costs more because you are paying for thousands of tokens of irrelevant context on every single call. The agent gets confused because it is holding 10 different roles simultaneously. Response quality degrades. And when you want to update how the agent handles, say, LinkedIn content, you are editing a single massive prompt that affects everything.

The better model is specialisation. The same way a real team works. You have a LinkedIn strategist. You have an accountant. You have a YouTube editor. Each one is excellent at their specific domain and has no opinion about things outside it.

Multi-Agent Architecture Overview

The architecture has two layers: a gateway and a set of specialist agents.

The gateway is a lightweight process that runs permanently. It connects to your messaging interface (Telegram, Slack, Discord - whatever you use to talk to your assistant). Its only job is to receive messages and route them to the correct specialist agent. It does not run Claude itself. It just decides who should handle the message.

The specialist agents are invoked on demand. When the gateway routes a message to the LinkedIn agent, it spawns a claude -p process with the LinkedIn system prompt and the relevant context. That process handles the task, responds, and terminates. No idle cost, no permanent memory pressure.

# Architecture diagram Telegram → Gateway (Bun/Grammy, always running) │ ├── General Agent # catch-all, admin ├── LinkedIn Agent # posts, comments, DMs ├── YouTube Agent # scripts, thumbnails, analytics ├── Newsletter Agent # Beehiiv, content calendar ├── Skool Agent # community management ├── Accountant Agent # Stripe, Xero, revenue └── Strategy Agent # planning, decisions, research

Gateway Pattern: Routing by Topic Thread

Telegram has a feature called Topics - you can create a group with multiple topic threads, each acting like a separate chat. This is the perfect routing mechanism. Each agent gets its own topic. When you post in the LinkedIn topic, the gateway knows to use the LinkedIn agent.

// gateway/router.ts import { Bot } from 'grammy' import { runAgent } from './agent-runner' const TOPIC_ROUTES: Record<number, string> = { 238: 'linkedin', 239: 'youtube', 240: 'newsletter', 241: 'skool', 242: 'accountant', 243: 'strategy', } export function setupRouter(bot: Bot) { bot.on('message', async (ctx) => { const topicId = ctx.message.message_thread_id const agentName = TOPIC_ROUTES[topicId] ?? 'general' const userMessage = ctx.message.text if (!userMessage) return await ctx.replyWithChatAction('typing') const response = await runAgent(agentName, userMessage) await ctx.reply(response, { message_thread_id: topicId, parse_mode: 'Markdown' }) }) }

Running Agents with claude -p

Each agent is invoked using the -p (print) flag, which runs Claude in non-interactive mode, outputs the response, and exits. This is what makes the architecture lightweight - agents are processes, not permanent servers.

// gateway/agent-runner.ts import { execFile } from 'child_process' import { promisify } from 'util' import { readFileSync } from 'fs' import { loadEnv } from './env' const exec = promisify(execFile) const env = loadEnv('/home/jarvis/.env') export async function runAgent(name: string, message: string): Promise<string> { const systemPrompt = readFileSync( `/home/jarvis/agents/${name}.md`, 'utf-8' ) const sharedContext = readFileSync( '/home/jarvis/context/MEMORY.md', 'utf-8' ) const fullPrompt = `${sharedContext}\n\n${systemPrompt}` const { stdout } = await exec('claude', [ '-p', message, '--system', fullPrompt, '--model', 'claude-opus-4-5' ], { env: { ...process.env, ...env }, timeout: 120000 // 2 minute timeout }) return stdout.trim() }

The 7 Specialist Agents

Each agent is a markdown file that serves as its system prompt. These files define personality, capabilities, tools, and focus area. Here is the structure for each:

General Agent

The catch-all. Handles anything that does not fit a specific topic. Knows about all the other agents and can hand off tasks. Has broad knowledge of the business but is not expert in any single domain.

LinkedIn Agent

Specialises in LinkedIn content strategy. Knows the posting cadence, which content formats work, how to write connection requests, how to analyse profile views and engagement. Has access to the content calendar and past post performance.

# /home/jarvis/agents/linkedin.md You are the LinkedIn specialist for Rahul Jindal AI. Your responsibilities: - Write and edit LinkedIn posts (thought leadership, case studies, hooks) - Draft connection request messages (personalised, not templony) - Analyse engagement data and suggest content pivots - Repurpose long-form content into LinkedIn carousel ideas - Track which content formats are performing Content rules: - No rhetorical questions - No em dashes - No staccato fragments ("Not X. Statement.") - Hooks should be specific and counter-intuitive - First line must stop the scroll without being clickbait

YouTube Agent

Scripts, titles, thumbnails, and analytics. Knows the channel's existing content, audience demographics, best-performing formats, and the content pipeline. Can pull YouTube Analytics data when given API access.

Newsletter Agent

Manages the Beehiiv newsletter. Writes editions, plans content calendar, tracks open rates and click rates, suggests repurposing opportunities. Knows the audience segment and content preferences.

Accountant Agent

The most powerful one for business owners. Pulls live data from Stripe (revenue, MRR, churn), Xero (expenses, invoices), and presents clean financial summaries. Can flag unusual expenses, compare month-on-month performance, and project revenue.

# Example accountant agent prompt that triggers data pull "What's my MRR this month?" # Agent executes: STRIPE_DATA=$(bash /home/jarvis/data/stripe.sh) XERO_DATA=$(bash /home/jarvis/data/xero.sh) # Then feeds this data into Claude for analysis

Strategy Agent

Long-horizon thinking. Reviews decisions, analyses options, suggests pivots. Has access to the full business context, historical performance, and can be prompted with specific strategic questions. This one benefits most from a longer context window.

Shared Context vs Agent-Specific Context

Not all context belongs in every agent. Here is the split:

Shared context (injected into every agent):

Agent-specific context (only in the relevant agent):

Keeping these separate reduces token cost and keeps each agent focused. The LinkedIn agent does not need to know how Stripe webhooks work.

Skills Directory: Reusable Workflows

Some tasks follow the same multi-step process every time. These become skills - markdown files that describe the workflow in enough detail that any agent can execute them.

/home/jarvis/skills/ ├── write-shorts.md # Research, write 30 short scripts, post to Trello ├── post-content.md # Post to TikTok, Instagram, YouTube Shorts, LinkedIn ├── youtube-thumbnail.md # Generate with fal.ai, attach to Trello card ├── create-invoice.md # Generate invoice, send via Xero or Stripe └── lead-follow-up.md # Pull meeting context, draft follow-up message

When an agent needs to execute a skill, the gateway loads the skill file and includes it in the context:

// If message references a known skill keyword, load the skill file const SKILL_KEYWORDS: Record<string, string> = { 'write scripts': 'write-shorts', 'post content': 'post-content', 'create invoice': 'create-invoice', } function detectSkill(message: string): string | null { for (const [keyword, skill] of Object.entries(SKILL_KEYWORDS)) { if (message.toLowerCase().includes(keyword)) { return readFileSync(`/home/jarvis/skills/${skill}.md`, 'utf-8') } } return null }

Data Helpers: Bash Scripts for Live Data

Agents are only useful if they have current data. Static context files go stale. The solution is bash scripts that pull live data from APIs at the moment the agent needs it.

#!/bin/bash # /home/jarvis/data/stripe.sh # Pulls current MRR, recent charges, and subscription count source /home/jarvis/.env # Get current month's revenue MONTH_START=$(date -d "$(date +%Y-%m-01)" +%s) curl -s https://api.stripe.com/v1/charges \ -u $STRIPE_SECRET_KEY: \ -d "created[gte]=$MONTH_START" \ -d "limit=100" \ | jq '.data | map(select(.paid==true)) | map(.amount) | add / 100'
#!/bin/bash # /home/jarvis/data/fireflies.sh # Gets last 5 meeting transcripts with summaries source /home/jarvis/.env curl -s -X POST https://api.fireflies.ai/graphql \ -H "Authorization: Bearer $FIREFLIES_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "{ transcripts(limit: 5) { title date summary action_items } }"}'

The agent runner calls these scripts before invoking Claude, then includes the output as part of the context:

// For the accountant agent, pre-fetch live data if (agentName === 'accountant') { const { stdout: stripeData } = await exec('bash', ['/home/jarvis/data/stripe.sh']) const { stdout: xeroData } = await exec('bash', ['/home/jarvis/data/xero.sh']) liveData = `## Live Financial Data\n${stripeData}\n${xeroData}` }

Cron Automations

The best agents are not reactive - they are proactive. Set up cron jobs for tasks that should happen on a schedule, without anyone asking:

# /home/jarvis/cron/morning-briefing.sh #!/bin/bash source /home/jarvis/.env # Pull live data STRIPE=$(bash /home/jarvis/data/stripe.sh) CALENDAR=$(bash /home/jarvis/data/calendar.sh) LEADS=$(bash /home/jarvis/data/ghl-pipeline.sh) # Run the strategy agent with morning briefing prompt BRIEFING=$(claude -p "Generate a morning intelligence briefing. Data: $STRIPE $CALENDAR $LEADS" \ --system "$(cat /home/jarvis/agents/strategy.md)" \ --model claude-opus-4-5) # Send to Telegram General topic curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \ -d "chat_id=$TELEGRAM_CHAT_ID" \ -d "message_thread_id=0" \ -d "text=$BRIEFING" \ -d "parse_mode=Markdown"
# Crontab (crontab -e as jarvis user) # Morning Intelligence - 5am daily 0 5 * * * /home/jarvis/cron/morning-briefing.sh >> /home/jarvis/logs/cron.log 2>&1 # Weekly Content Planning - Saturday 5:30am 30 5 * * 6 /home/jarvis/cron/weekly-content-plan.sh >> /home/jarvis/logs/cron.log 2>&1

Cost Comparison

This is why the architecture matters from a business perspective.

Single AgentMulti-Agent (Specialist)
System prompt~8,000 tokens~2,000 tokens
Per message~12,000 tokens~4,000 tokens
Cost per message~$0.15~$0.03
Monthly (100 msgs/day)~$450~$90

That is roughly 60% cheaper per message, at higher quality because each agent is focused on its domain. At 50 messages per day, the savings compound to hundreds of dollars per month.

How to Add a New Agent

Adding a new specialist is straightforward:

  1. Create the agent system prompt at /home/jarvis/agents/new-agent.md
  2. Add a new Telegram topic in your group and note its thread ID
  3. Add the topic ID to route mapping in gateway/router.ts
  4. If the agent needs live data, create a bash script in /home/jarvis/data/
  5. Update shared context (MEMORY.md) if new facts are relevant to multiple agents
  6. Restart the gateway: pm2 restart jarvis-gateway
  7. Test by posting a message in the new Telegram topic
Tip: When creating a new agent, start with a minimal system prompt and expand it over the first few days based on what you actually ask it. Over-engineering the prompt upfront creates false assumptions about what context will be useful.

Want a multi-agent system built for your business?

I can design and deploy a custom agent architecture tailored to your specific workflows.

Book a Call
Next Guide
Parallelization Patterns