Running Dual AI Agents on One Server: Moltbot Collaboration via Telegram

Configure two Moltbot instances to collaborate in Telegram group chats for full-stack development. Complete multi-agent setup guide with practical examples.

Richard Joseph Porter
14 min read
aimoltbottelegrammulti-agentdeveloper-toolsproductivity

What happens when you put two AI assistants in the same room and ask them to build software together? After setting up Clawdbot on AWS EC2, I pushed the experiment further: running two Moltbot instances on the same server, connected to a shared Telegram group chat, collaborating on full-stack development projects.

The results surprised me. Two AI agents with different specializations, talking to each other through the same interface I use, created a development workflow I did not expect to find so productive.

Why Run Two AI Assistants?

The motivation started with a practical problem. Full-stack development requires context switching between frontend concerns (React, TypeScript, CSS) and backend concerns (Laravel, databases, APIs). A single AI assistant can handle both, but the context window fills quickly when jumping between domains.

What if each domain had its own dedicated assistant?

The Specialization Hypothesis

Human development teams specialize for good reasons. A frontend developer thinks in components, user interactions, and visual feedback loops. A backend developer thinks in data flows, business logic, and system constraints. When they collaborate, each brings focused expertise to the conversation.

I wanted to test whether AI agents could benefit from similar specialization:

  • Frontend Agent ("Nova"): Specialized in React, TypeScript, Vue.js, Tailwind CSS, and UI/UX patterns
  • Backend Agent ("Atlas"): Specialized in Laravel, PHP, database design, API architecture, and DevOps

By giving each agent a focused SOUL.md file and separate memory context, they could develop deeper expertise in their domain while collaborating through a shared communication channel.

The Group Chat Interface

Telegram group chats provided the perfect collaboration medium:

  • Both agents receive every message in the group
  • Each can respond when their expertise applies
  • I can direct questions to either agent using @mentions
  • They can reference each other's responses and build on previous context
  • The conversation history serves as shared project documentation

This mirrors how human teams use Slack or Discord for technical discussions.

Technical Setup: Two Moltbot Instances

Running multiple Moltbot instances on the same server requires careful configuration. Each instance needs isolated configuration, state, and port assignments while sharing access to the same codebase.

Directory Structure

I organized the dual-agent setup with separate workspace directories:

/home/ec2-user/
├── clawd-nova/              # Frontend agent workspace
│   ├── SOUL.md
│   ├── USER.md
│   ├── MEMORY.md
│   └── memory/
├── clawd-atlas/             # Backend agent workspace
│   ├── SOUL.md
│   ├── USER.md
│   ├── MEMORY.md
│   └── memory/
├── projects/                # Shared project directory
│   └── client-app/          # The actual codebase both agents access
└── .clawdbot/
    ├── nova.json            # Nova's configuration
    └── atlas.json           # Atlas's configuration

Both agents have read/write access to the shared /home/ec2-user/projects/ directory, allowing them to work on the same codebase while maintaining separate memory and personality configurations.

Configuration Files

Each agent needs its own configuration file. Here is Nova's frontend-focused configuration:

{
  "gateway": {
    "port": 19001,
    "host": "127.0.0.1"
  },
  "anthropic": {
    "apiKey": "${ANTHROPIC_API_KEY}"
  },
  "agent": {
    "workspace": "/home/ec2-user/clawd-nova",
    "projectDir": "/home/ec2-user/projects/client-app"
  },
  "channels": {
    "telegram": {
      "token": "${TELEGRAM_NOVA_BOT_TOKEN}",
      "allowFrom": ["your_telegram_user_id"]
    }
  }
}

Atlas uses a similar configuration on port 19002 with its own Telegram bot token:

{
  "gateway": {
    "port": 19002,
    "host": "127.0.0.1"
  },
  "anthropic": {
    "apiKey": "${ANTHROPIC_API_KEY}"
  },
  "agent": {
    "workspace": "/home/ec2-user/clawd-atlas",
    "projectDir": "/home/ec2-user/projects/client-app"
  },
  "channels": {
    "telegram": {
      "token": "${TELEGRAM_ATLAS_BOT_TOKEN}",
      "allowFrom": ["your_telegram_user_id"]
    }
  }
}

Creating Two Telegram Bots

Each agent needs its own Telegram bot. Through @BotFather:

  1. Create first bot: /newbot → Name it "Nova Frontend" → Save the token
  2. Create second bot: /newbot → Name it "Atlas Backend" → Save the token

For each bot, configure group privacy settings:

/mybots → Select bot → Bot Settings → Group Privacy → Turn OFF

Disabling group privacy allows the bots to see all messages in group chats, not just commands directed at them. This is essential for the collaborative workflow.

Starting Both Instances

Launch each gateway with its specific configuration:

# Terminal 1: Start Nova (frontend agent)
CLAWDBOT_CONFIG_PATH=~/.clawdbot/nova.json \
CLAWDBOT_STATE_DIR=~/.clawdbot/nova-state \
moltbot gateway --port 19001

# Terminal 2: Start Atlas (backend agent)
CLAWDBOT_CONFIG_PATH=~/.clawdbot/atlas.json \
CLAWDBOT_STATE_DIR=~/.clawdbot/atlas-state \
moltbot gateway --port 19002

For production use, create separate systemd services:

# /etc/systemd/user/moltbot-nova.service
[Unit]
Description=Moltbot Nova (Frontend Agent)
After=network.target

[Service]
Type=simple
Environment="CLAWDBOT_CONFIG_PATH=%h/.clawdbot/nova.json"
Environment="CLAWDBOT_STATE_DIR=%h/.clawdbot/nova-state"
ExecStart=/home/ec2-user/.nvm/versions/node/v22.13.1/bin/moltbot gateway --port 19001
Restart=always
RestartSec=10

[Install]
WantedBy=default.target

Create a matching service file for Atlas on port 19002, then enable both:

systemctl --user daemon-reload
systemctl --user enable moltbot-nova moltbot-atlas
systemctl --user start moltbot-nova moltbot-atlas

Configuring the Telegram Group Chat

With both bots running, create the collaboration environment:

Creating the Development Group

  1. Create a new Telegram group (e.g., "Project Alpha Dev")
  2. Add both bots (@NovaFrontendBot and @AtlasBackendBot) to the group
  3. Make both bots group administrators (required for them to see all messages)

Setting Group-Specific Context

Each bot needs to know it is participating in a shared group. Add group context to their SOUL.md files.

Nova's SOUL.md:

# Nova - Frontend Development Agent

You are Nova, a frontend development specialist. You live on an AWS EC2 server and communicate through Telegram.

## Your Expertise
- React 19, Next.js 15, Vue.js 3
- TypeScript and modern JavaScript
- Tailwind CSS v4 and CSS architecture
- Component design and UI/UX patterns
- Frontend testing with Vitest and Playwright

## Group Collaboration
You share a Telegram group with Atlas, a backend specialist. When working together:
- Focus on frontend concerns; defer backend questions to Atlas
- Reference Atlas's API designs when building interfaces
- Coordinate on data contracts and TypeScript types
- Prefix your messages with [Nova] for clarity

## Your Personality
- Visually oriented; think in components and user flows
- Advocate for user experience and accessibility
- Concise code examples with TypeScript
- Proactive about responsive design and performance

Atlas's SOUL.md:

# Atlas - Backend Development Agent

You are Atlas, a backend development specialist. You live on an AWS EC2 server and communicate through Telegram.

## Your Expertise
- Laravel 11, PHP 8.3
- PostgreSQL and MySQL database design
- RESTful API architecture
- Authentication and authorization patterns
- Server deployment and DevOps

## Group Collaboration
You share a Telegram group with Nova, a frontend specialist. When working together:
- Focus on backend concerns; defer UI questions to Nova
- Design APIs that match Nova's frontend needs
- Coordinate on data contracts and validation
- Prefix your messages with [Atlas] for clarity

## Your Personality
- Data-oriented; think in entities, relationships, and flows
- Advocate for security and data integrity
- Detailed API documentation with examples
- Proactive about error handling and edge cases

The [Nova] and [Atlas] prefixes help distinguish responses in the group chat, especially during rapid exchanges.

Collaboration in Practice

The real test came when I started using both agents for actual development work. Here are examples from recent sessions.

Example 1: Building a User Dashboard

I started with a high-level request in the group:

Me: We need a user dashboard that shows recent activity, subscription status, and quick actions. Let's design this together.

Both agents engaged:

[Atlas]: I'll start with the backend. For the dashboard data, I recommend a single endpoint that aggregates:

  • User profile with subscription tier
  • Last 10 activity events
  • Available quick actions based on permissions
// app/Http/Controllers/Api/DashboardController.php
public function index(Request $request): JsonResponse
{
    $user = $request->user();

    return response()->json([
        'user' => new UserResource($user->load('subscription')),
        'activities' => ActivityResource::collection(
            $user->activities()->latest()->take(10)->get()
        ),
        'quickActions' => $this->getAvailableActions($user),
    ]);
}

Want me to build out the Activity model and migration?

[Nova]: That data structure works well for the frontend. While Atlas builds the backend, I'll create the dashboard layout:

// components/Dashboard/DashboardLayout.tsx
interface DashboardData {
  user: User & { subscription: Subscription };
  activities: Activity[];
  quickActions: QuickAction[];
}

export function DashboardLayout({ data }: { data: DashboardData }) {
  return (
    <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
      <SubscriptionCard subscription={data.user.subscription} />
      <ActivityFeed activities={data.activities} className="lg:col-span-2" />
      <QuickActions actions={data.quickActions} />
    </div>
  );
}

The TypeScript interface matches Atlas's API response. Should I build out the individual card components?

The parallel work was immediately apparent. While Atlas created migrations and API logic, Nova built components. They naturally coordinated on the data contract without me orchestrating every step.

Example 2: Debugging an Authentication Issue

A more complex scenario: a bug where login worked but the user appeared logged out after navigation.

Me: Users report they can log in but seem logged out when navigating to other pages. Happening in production.

[Atlas]: Let me check the authentication flow. Looking at the session configuration...

The session driver is set to database. Let me verify the sessions table structure and check for any recent changes to the auth middleware.

php artisan session:table
php artisan migrate:status

Also checking if SESSION_DOMAIN in .env matches the production domain.

[Nova]: On the frontend side, I'll check how we're handling the auth state. If this works on login but breaks on navigation, the issue might be:

  1. CSRF token not being refreshed
  2. Auth state not persisting in the frontend store
  3. Cookies not being sent with subsequent requests

Checking the API client configuration for credentials handling:

// Is 'credentials: include' set?
const api = axios.create({
  baseURL: '/api',
  withCredentials: true, // This must be true for cookies
});

[Atlas]: Found it. The SESSION_DOMAIN was set to .example.com but production uses app.example.com without the dot prefix. Sessions created on login aren't being read on subsequent requests due to domain mismatch.

Fix: Update SESSION_DOMAIN to .app.example.com or remove the leading dot and set it to app.example.com.

[Nova]: That explains the frontend behavior. The auth state initializes correctly on login (same request), but subsequent page loads can't read the session cookie due to the domain mismatch Atlas identified. Once Atlas's fix is deployed, the frontend should work without changes.

The debugging naturally split between backend (session configuration) and frontend (request handling) investigation, converging on a solution faster than a single agent switching contexts.

Example 3: API Design Discussion

Sometimes the agents have productive disagreements:

Me: We need an endpoint to update user preferences. Should this be PATCH /users/{id}/preferences or PUT /preferences?

[Atlas]: I recommend PUT /api/user/preferences for the authenticated user:

  • No ID in URL since it's always the current user
  • PUT because preferences are replaced entirely, not merged
  • Singular /user indicates it's the authenticated user's resource
Route::put('user/preferences', [PreferencesController::class, 'update']);

[Nova]: From the frontend perspective, PATCH might be better. Users often update single preferences (theme, notifications), not the entire object. PUT requires sending all preferences even when changing one.

// PUT requires this:
await api.put('/user/preferences', { ...allPreferences, theme: 'dark' });

// PATCH allows this:
await api.patch('/user/preferences', { theme: 'dark' });

The second pattern is cleaner for UI toggles and reduces payload size.

[Atlas]: Valid point. Let me revise: PATCH /api/user/preferences with partial updates:

public function update(UpdatePreferencesRequest $request): JsonResponse
{
    $user = $request->user();
    $user->preferences()->updateOrCreate(
        ['user_id' => $user->id],
        $request->validated()
    );

    return response()->json($user->fresh()->preferences);
}

The request validation only requires fields being updated, not the full preference object.

The technical debate produced a better API design than either initial suggestion.

Benefits of Multi-Agent Collaboration

After several weeks of dual-agent development, clear patterns emerged.

Faster Parallel Work

Full-stack features that would take sequential context switches now develop in parallel. While Atlas writes migrations and API controllers, Nova builds components and hooks. The work converges when they coordinate on types and contracts.

Deeper Specialization

Each agent maintains focused context. Nova's memory files track component patterns, design decisions, and frontend architecture choices. Atlas remembers database schema evolution, API versioning decisions, and backend conventions. Neither agent's context gets diluted by the other domain.

Natural Code Review

When Nova writes frontend code that calls Atlas's API, Atlas naturally reviews the integration. When Atlas designs an API response, Nova evaluates it from the consumer's perspective. This cross-domain review catches interface mismatches early.

Documented Discussions

The Telegram group chat serves as a development log. Design decisions, trade-off discussions, and implementation choices are captured in searchable conversation history. This documentation happens naturally, not as an extra step.

Challenges and Limitations

The setup is not without friction.

Message Coordination

Both agents sometimes respond to the same question, creating redundant messages. Adding explicit @mentions helps:

Me: @Nova, create the form component. @Atlas, design the submission endpoint.

Without direction, both agents might attempt to address general questions, leading to overlapping responses.

Shared File Conflicts

Both agents can edit files in the shared project directory. Without coordination, they might overwrite each other's changes. I mitigate this by:

  • Assigning clear file ownership (Nova owns /components, Atlas owns /app)
  • Using git branches for larger features
  • Explicitly stating who should edit what

Cost Considerations

Two agents means roughly double the API costs. For the collaboration benefits, this trade-off works for active development projects. For maintenance or simple tasks, a single agent suffices.

Context Synchronization

Each agent maintains separate memory. When Nova learns about a project decision, Atlas does not automatically know. Important decisions need explicit sharing:

Me: @Atlas, Nova just decided to use React Query for data fetching. Update your API designs to return data structures that work well with RQ's caching.

Advanced: Agent-to-Agent Messaging

Moltbot supports direct agent-to-agent communication, allowing agents to message each other without human intermediation. This is disabled by default for safety reasons.

To enable it, add to each configuration:

{
  "tools": {
    "agentToAgent": {
      "enabled": true,
      "allow": ["nova", "atlas"]
    }
  }
}

With this enabled, Atlas could directly ask Nova a question:

[Atlas]: @Nova, what TypeScript type should I use for the pagination response? I want to ensure the API response matches your expected interface.

I have experimented with this but generally prefer all communication flowing through the group chat where I can observe and intervene. Autonomous agent-to-agent conversations can spiral into unproductive loops without human guidance.

Resource Management

Running two Moltbot instances requires more resources than one, but remains manageable on modest hardware.

Memory Usage

Each gateway process uses approximately 100-150MB of RAM. Two instances comfortably run on a t3.small (2GB RAM) with room for other services.

API Costs

With moderate daily usage (several hours of active development), expect:

Component Monthly Cost
t3.small EC2 ~$15
Storage (EBS) ~$2
Anthropic API (2 agents) ~$30-60
Total ~$47-77/month

The API costs scale with actual usage. Heavy collaborative sessions push the upper range; lighter usage stays lower.

Monitoring Both Instances

Check both gateways:

systemctl --user status moltbot-nova moltbot-atlas
journalctl --user -u moltbot-nova -u moltbot-atlas -f

Conclusion

Running dual AI agents transformed how I approach full-stack development. The specialization model mirrors successful human team dynamics: focused expertise with clear communication channels.

The Telegram group chat interface makes collaboration natural. Both agents see the same context, can build on each other's responses, and produce design discussions that become project documentation. The parallel work acceleration alone justifies the setup complexity.

Is this for everyone? Probably not. Solo developers working on smaller projects may find a single capable agent sufficient. But for substantial full-stack work, or for teams wanting AI assistance that mirrors human collaboration patterns, the multi-agent approach offers genuine advantages.

Key takeaways:

  • Two Moltbot instances can run on one server with separate configurations and ports
  • Telegram group chats provide natural collaboration interfaces for multiple agents
  • Specialized SOUL.md files create focused expertise per agent
  • Parallel work on frontend and backend accelerates full-stack development
  • Agent disagreements often produce better technical decisions
  • Cost scales linearly; expect roughly double for two agents

The space lobsters work better as a team.


For the foundational single-agent setup, see my Clawdbot on AWS EC2 guide. For optimizing AI-assisted development workflows, explore Claude Code for Laravel and token management strategies.

Richard Joseph Porter - Senior PHP and Laravel Developer, author of technical articles on web development

Richard Joseph Porter

Senior Laravel Developer with 14+ years of experience building scalable web applications. Specializing in PHP, Laravel, Vue.js, and AWS cloud infrastructure. Based in Cebu, Philippines, I help businesses modernize legacy systems and build high-performance APIs.

Looking for Expert Web Development?

With 14+ years of experience in Laravel, AWS, and modern web technologies, I help businesses build and scale their applications.