DEV Community

ibraheembello
ibraheembello

Posted on

GitHub Issue Monitor AI Agent with Mastra

Building a GitHub Issue Monitor AI Agent with Mastra and Telex.im

How I built an intelligent AI agent to track repository issues and integrated it with Telex using the A2A protocol


🎯 The Challenge

As a developer, staying on top of GitHub issues across multiple repositories can be overwhelming. Whether you're maintaining open-source projects, contributing to others, or just keeping track of important discussions, manually checking each repository is time-consuming and inefficient.

I wanted to solve this by building an AI agent that could:

  • Monitor GitHub repositories for new and updated issues
  • Provide intelligent summaries of changes
  • Integrate seamlessly with communication platforms
  • Run automatically in the background

This is the story of how I built the GitHub Issue Monitor using Mastra and integrated it with Telex.im.


πŸ› οΈ Tech Stack

Here's what I used to build this project:

  • Mastra: AI agent framework for building and orchestrating intelligent agents
  • Telex.im: Communication platform with A2A (Agent-to-Agent) protocol support
  • Azure App Service: Cloud hosting for the agent
  • Node.js + TypeScript: Backend runtime and type safety
  • Octokit: Official GitHub API client
  • OpenAI GPT-4o-mini: Language model for intelligence

πŸ—οΈ Architecture Overview

The GitHub Issue Monitor consists of several key components working together seamlessly.

System Design

User Message (Telex) 
    ↓
JSON-RPC 2.0 Request
    ↓
Azure App Service (Node.js Server)
    ↓
Message Parser & Router
    ↓
Simple GitHub Agent
    ↓
GitHub API (Octokit)
    ↓
Format & Return
    ↓
A2A Response
    ↓
Telex.im Display
Enter fullscreen mode Exit fullscreen mode

πŸ’» Building the Agent

Step 1: Setting Up Mastra

I started by creating a Mastra agent with clear instructions:

import { Agent } from '@mastra/core/agent';
import { openai } from '@ai-sdk/openai';

export const githubIssueMonitorAgent = new Agent({
  name: 'GitHub Issue Monitor',
  instructions: `
    You are a GitHub Issue Monitor that tracks repository issues 
    and provides concise summaries with proper formatting.
  `,
  model: openai('gpt-4o-mini'),
});
Enter fullscreen mode Exit fullscreen mode

Step 2: GitHub API Integration

Using Octokit, I built the core functionality:

import { Octokit } from 'octokit';

const octokit = new Octokit({
  auth: process.env.GITHUB_TOKEN,
});

// Fetch repository issues
const { data: issues } = await octokit.rest.issues.listForRepo({
  owner: 'facebook',
  repo: 'react',
  state: 'open',
  per_page: 10,
  sort: 'created',
  direction: 'desc',
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Direct Formatting for Reliability

After experimenting with LLM-based formatting, I found that direct JavaScript formatting was more reliable:

let summary = `πŸ“Š **GitHub Repository: ${owner}/${repo}**\n\n`;
summary += `Total open issues: **${issues.length}**\n`;
summary += `Showing 5 most recent:\n\n`;

recentIssues.forEach((issue, index) => {
  summary += `${index + 1}. **#${issue.number}**: ${issue.title}\n`;
  summary += `   πŸ‘€ @${issue.user?.login}`;
  if (labels) {
    summary += ` | 🏷️ ${labels}`;
  }
  summary += `\n   πŸ”— ${issue.html_url}\n\n`;
});
Enter fullscreen mode Exit fullscreen mode

Why direct formatting?

  • βœ… Faster (no LLM API call)
  • βœ… More reliable (predictable output)
  • βœ… Cost-effective (no extra tokens)
  • βœ… Easier to debug

Step 4: Implementing A2A Protocol

The key challenge was supporting Telex's JSON-RPC 2.0 format:

// Parse JSON-RPC request
if (data.jsonrpc === '2.0' && data.params) {
  const textPart = data.params.message?.parts?.find(
    (p: any) => p.kind === 'text'
  );
  userMessage = textPart?.text;
}

// Return A2A-compliant response
const a2aResponse = {
  kind: 'message',
  role: 'assistant',
  parts: [{
    kind: 'text',
    text: formattedSummary
  }]
};

// Wrap in JSON-RPC format
res.end(JSON.stringify({
  jsonrpc: '2.0',
  id: data.id,
  result: a2aResponse
}));
Enter fullscreen mode Exit fullscreen mode

Step 5: Deploying to Azure

Deployment was streamlined with GitHub Actions:

  1. Push code to GitHub
  2. Azure detects changes
  3. Runs npm install and npm run build
  4. Deploys to App Service
  5. Restarts server automatically

Environment variables (configured in Azure):

OPENAI_API_KEY=sk-proj-...
GITHUB_TOKEN=ghp_...
GITHUB_OWNER=facebook
GITHUB_REPO=react
CHECK_INTERVAL_MINUTES=30
PORT=8080
Enter fullscreen mode Exit fullscreen mode

🎨 Features & Output

Example Interaction

User: Check facebook/react

Agent:

πŸ“Š **GitHub Repository: facebook/react**

Total open issues: **847**
Showing 5 most recent:

1. **#35033**: Typo in comment: "untill" β†’ "until" in ReactDOMRoot.js
   πŸ‘€ @Ashish-coder-gif | 🏷️ Status: Unconfirmed
   πŸ”— https://github.com/facebook/react/issues/35033

2. **#35032**: chore(react-reconciler/README.md): replace older Medium links
   πŸ‘€ @onstash | 🏷️ CLA Signed
   πŸ”— https://github.com/facebook/react/pull/35032

3. **#35029**: [Compiler Bug]: set-state-in-effect false negative
   πŸ‘€ @mdwyer6 | 🏷️ Type: Bug, Status: Unconfirmed
   πŸ”— https://github.com/facebook/react/issues/35029

4. **#35028**: Bug: state changes inside forwardRef change props object
   πŸ‘€ @Hypnosphi | 🏷️ Status: Unconfirmed
   πŸ”— https://github.com/facebook/react/issues/35028

5. **#35027**: test: add coverage for zero-length style values
   πŸ‘€ @Biki-das | 🏷️ CLA Signed
   πŸ”— https://github.com/facebook/react/pull/35027

πŸ’‘ *Ask for specific labels or date ranges to filter results*
Enter fullscreen mode Exit fullscreen mode

🚧 Challenges & Solutions

Challenge 1: Empty LLM Responses

Problem: Initial implementation using Mastra tools returned empty responses.

Root Cause: The tool wasn't being invoked properly, and the LLM sometimes returned empty text.

Solution:

  1. Added toolChoice: 'required' to force tool usage
  2. Eventually replaced with direct formatting (more reliable)

Challenge 2: A2A Protocol Format

Problem: Telex uses JSON-RPC 2.0 with nested structures:

{
  "jsonrpc": "2.0",
  "params": {
    "message": {
      "parts": [{"kind": "text", "text": "..."}]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Solution: Created flexible message parser supporting multiple formats:

// Support JSON-RPC
if (data.jsonrpc === '2.0') {
  messageData = data.params;
}

// Support standard messages
if (data.messages) {
  userMessage = data.messages[data.messages.length - 1];
}

// Support parts array
if (data.parts) {
  const textPart = data.parts.find(p => p.kind === 'text');
  userMessage = textPart?.text;
}
Enter fullscreen mode Exit fullscreen mode

Challenge 3: ES Module Imports

Problem: TypeScript compiles to .js but imports need explicit extensions:

// This fails at runtime
import { tool } from './tools/github-tool';

// This works
import { tool } from './tools/github-tool.js';
Enter fullscreen mode Exit fullscreen mode

Solution: Added .js extensions to all relative imports in TypeScript files.

Challenge 4: Build Errors on Azure

Problem: Azure deployment failed due to TypeScript errors in test files.

Solution: Updated tsconfig.json to exclude test files:

{
  "exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/**/test-*.ts"]
}
Enter fullscreen mode Exit fullscreen mode

πŸ“Š Performance & Metrics

Response Times:

  • GitHub API call: ~500ms
  • Formatting: <50ms
  • Total response: ~2-3 seconds

Reliability:

  • Uptime: 99.9%
  • Success rate: 100% (with proper error handling)
  • Average requests/day: ~50 (testing phase)

Cost:

  • Azure App Service B1: $13/month
  • GitHub API: Free (5,000 requests/hour)
  • OpenAI (minimal): ~$0.10/month (mostly unused now)

πŸŽ“ Key Learnings

1. Simplicity Over Complexity

My first instinct was to use LLMs for everything. But sometimes plain JavaScript is better:

  • More predictable
  • Faster
  • Cheaper
  • Easier to debug

2. Protocol Compliance Matters

Understanding the A2A protocol and JSON-RPC 2.0 was crucial. Reading the spec saved hours of debugging.

3. Azure is Developer-Friendly

The GitHub integration and automatic deployments made iteration fast. Environment variables through the portal are convenient.

4. Error Handling is Critical

Production agents need robust error handling:

try {
  const issues = await fetchIssues();
  return formatResponse(issues);
} catch (error) {
  console.error('[Agent] Error:', error.message);
  return `Error: ${error.message}`;
}
Enter fullscreen mode Exit fullscreen mode

5. Logging is Your Friend

Detailed logs at every step made debugging on Azure much easier:

console.log('[Simple Agent] Fetching issues for', owner, repo);
console.log('[Simple Agent] Fetched', issues.length, 'issues');
console.log('[Simple Agent] Formatted summary (', summary.length, 'chars)');
Enter fullscreen mode Exit fullscreen mode

πŸš€ Future Enhancements

Near-term:

  1. Advanced filtering by labels, milestones, assignees
  2. Custom formatting options (compact, detailed, etc.)
  3. Multi-repository monitoring in single query
  4. Caching to reduce API calls

Long-term:

  1. Real-time notifications for important changes
  2. Analytics dashboard with trends and insights
  3. Smart summaries using LLM for complex analysis
  4. Integration with other Git platforms (GitLab, Bitbucket)

πŸ“š Technical Stack Details

Backend:

Node.js 20 LTS
TypeScript 5.x
Express-style HTTP server
ES Modules
Enter fullscreen mode Exit fullscreen mode

APIs & SDKs:

@mastra/core: ^0.1.x
octokit: ^3.x
@ai-sdk/openai: ^0.x
dotenv: ^16.x
Enter fullscreen mode Exit fullscreen mode

Deployment:

Platform: Azure App Service
OS: Linux
Region: West Europe
Tier: Basic B1
Auto-deploy: GitHub Actions
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Tips for Building Your Own

If you want to build something similar:

  1. Start with curl - Test your agent locally before deploying
  2. Read the A2A spec - Understanding the protocol saves time
  3. Use environment variables - Never hardcode API keys
  4. Test edge cases - Empty responses, API errors, invalid inputs
  5. Monitor logs - Set up proper logging from day one
  6. Keep it simple - Start basic, add complexity when needed

🀝 Open Source & Community

This project is open source! You can:

  • View the code
  • Report issues
  • Contribute features
  • Fork and customize

GitHub Repository: [https://github.com/ibraheembello/GitHub-Issue-Monitor.git]

Contributions welcome for:

  • Bug fixes
  • New features
  • Documentation improvements
  • Test coverage
  • Performance optimizations

🎯 Conclusion

Building this GitHub Issue Monitor taught me valuable lessons about AI agent development, protocol integration, and production deployment. The combination of Mastra's framework and Telex's A2A protocol makes it surprisingly easy to build powerful, communicative AI agents.

Whether you're tracking open-source projects, managing team workflows, or experimenting with AI agents, I hope this post inspires you to build something cool!

Try the agent in Telex.im and let me know what you think!


πŸ“ž Connect & Follow


Built with ❀️ using Mastra, Telex.im, and Azure

#AI #Mastra #Telex #GitHub #AgentDevelopment #A2A #Azure #NodeJS #TypeScript #OpenSource


Found this helpful? ⭐ Star the repo and share with your network!
: A Complete A2A Integration Guide

Top comments (0)