<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Obinna Aguwa</title>
    <description>The latest articles on DEV Community by Obinna Aguwa (@macmartins).</description>
    <link>https://dev.to/macmartins</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F218166%2F704a3078-8f9d-4667-9566-f9290c60e271.jpeg</url>
      <title>DEV Community: Obinna Aguwa</title>
      <link>https://dev.to/macmartins</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/macmartins"/>
    <language>en</language>
    <item>
      <title>Building an AI-Powered Migration Pathways Agent with Go and the A2A Protocol</title>
      <dc:creator>Obinna Aguwa</dc:creator>
      <pubDate>Mon, 03 Nov 2025 21:42:13 +0000</pubDate>
      <link>https://dev.to/macmartins/building-an-ai-powered-migration-pathways-agent-with-go-and-the-a2a-protocol-22gm</link>
      <guid>https://dev.to/macmartins/building-an-ai-powered-migration-pathways-agent-with-go-and-the-a2a-protocol-22gm</guid>
      <description>&lt;p&gt;Planning to relocate internationally? The visa research process can be overwhelming, with countless pathways, varying costs, complex requirements, and constantly changing policies. I built an AI agent to solve this: a real-time migration advisor that analyzes your profile and returns the single best visa pathway, complete with costs, processing times, and actionable next steps.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk through how I built this agent using &lt;strong&gt;Google's Gemini LLM&lt;/strong&gt;, the &lt;strong&gt;A2A (Agent-to-Agent) protocol&lt;/strong&gt;, and deployed it on &lt;strong&gt;Heroku&lt;/strong&gt; for seamless integration with platforms like &lt;a href="https://telex.im/" rel="noopener noreferrer"&gt;Telex.im.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all, Telex is a collaboration workspace like Slack that allows developers to create AI Agents called AI Coworkers. The AI coworkers will work like a real human colleague. I might go in-depth in another article. For now, let's jump into the step-by-step process I took in building this migration pathways AI Agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does It Do?
&lt;/h2&gt;

&lt;p&gt;The Migration Pathways Agent takes a simple natural language query like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'm a software engineer from Nigeria wanting to move to Canada with a $10,000 budget"&lt;br&gt;
And returns a structured response:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Best Migration Option: Express Entry (Federal Skilled Worker)&lt;/span&gt;
This pathway is often the most straightforward option for skilled professionals seeking permanent residency in Canada, especially if they possess strong English or French skills, relevant work experience, and educational qualifications.
&lt;span class="gs"&gt;**Key Details:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Processing time: 6–12 months
&lt;span class="p"&gt;-&lt;/span&gt; Cost: $2,300 - $3,000 (including application fees, language testing, ECA, and settlement funds)
&lt;span class="p"&gt;-&lt;/span&gt; Success rate: Medium to High (dependent on CRS score relative to current cut-off scores)
&lt;span class="p"&gt;-&lt;/span&gt; Main requirements: Minimum of one year of skilled work experience, Language proficiency (CLB 7 or higher in English or French), Educational Credential Assessment (ECA) for foreign education
Next step: Take an IELTS or CELPIP test and get your educational credentials assessed by a recognized organization (e.g., World Education Services - WES).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The system consists of three main components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────┐
│ CLIENT/USER │
└─────────┬───────────┘
 │ HTTP
┌─────────▼───────────┐
│ A2A PROTOCOL │
│ ┌─────────────────┐ │
│ │ Agent Card │ │
│ │ JSON-RPC 2.0 │ │
│ └─────────────────┘ │
└─────────┬───────────┘
 │
┌─────────▼───────────┐
│ MIGRATION AGENT │
│ ┌─────────────────┐ │
│ │ Query Parser │ │
│ │ Task Manager │ │
│ │ Gemini Client │ │
│ └─────────────────┘ │
└─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. A2A Protocol Layer
&lt;/h3&gt;

&lt;p&gt;The A2A (Agent-to-Agent) protocol standardizes how AI agents communicate. I implemented two key endpoints:&lt;br&gt;
&lt;strong&gt;Agent Card&lt;/strong&gt; (&lt;code&gt;GET /.well-known/agent.json&lt;/code&gt;):&lt;br&gt;
Returns metadata about the agent's capabilities, supported methods, and configuration.&lt;br&gt;
&lt;strong&gt;Planner Endpoint&lt;/strong&gt; (&lt;code&gt;POST /a2a/planner&lt;/code&gt;):&lt;br&gt;
Accepts JSON-RPC 2.0 requests with methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;message/send&lt;/code&gt; - Send a migration query&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tasks/get&lt;/code&gt; - Retrieve task results&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tasks/send&lt;/code&gt; - Legacy task submission
### 2. The Go Server
I chose Go for its simplicity, performance, and excellent Heroku support. The server structure:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MigrationAgent&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;gemini&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GeminiClient&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Key design decisions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In-memory task storage&lt;/strong&gt;: Simple map for task management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded agent card&lt;/strong&gt;: Using Go's &lt;code&gt;embed&lt;/code&gt; package to serve the agent.json&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible message parsing&lt;/strong&gt;: Supports both Telex's format and standard A2A
### 3. Gemini Integration
The magic happens in the Gemini client. Here's how I structured the prompt:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GeminiClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`You are a migration planning expert.
CRITICAL BEHAVIOR RULES:
- Never ask the user for additional information
- Extract profession, origin country, and destination country from the query
- If information is unclear, make reasonable assumptions
- Output exactly ONE best migration option
USER QUERY:
"`&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;userQuery&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;`"
`&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c"&gt;// … rest of prompt&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why this approach?&lt;/strong&gt;&lt;br&gt;
Initially, I tried parsing professions, countries, and origins with hardcoded maps. Bad idea. Users said "USA" but the agent suggested Canada because my parsing was too rigid.&lt;br&gt;
&lt;strong&gt;The fix&lt;/strong&gt;: Let Gemini extract ALL information from natural language. This supports any country, any profession, any language - no maintenance required.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation Deep Dive
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Setting Up the Gemini Client
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GeminiClient&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;APIKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;BaseURL&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewGeminiClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;GeminiClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;GeminiClient&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;APIKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GEMINI_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;BaseURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://generativelanguage.googleapis.com/v1beta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"gemini-2.0-flash-exp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I used &lt;code&gt;gemini-2.0-flash-exp&lt;/code&gt; for its speed and strong reasoning capabilities - critical for extracting structured information from unstructured queries.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Task Processing Flow
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MigrationAgent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ProcessTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;taskID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c"&gt;// 1. Create task with "working" state&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;taskID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TaskStatus&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"working"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c"&gt;// 2. Extract user query from message parts&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userQuery&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;userQuery&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c"&gt;// 3. Query Gemini&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;responseText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gemini&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMigrationPathways&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;userQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Budget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c"&gt;// 4. Update task with results&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TaskStatus&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;StatusMessage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;Kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;responseText&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;MessageID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;messageID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;TaskID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;taskID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 3: A2A Response Format
&lt;/h3&gt;

&lt;p&gt;The A2A spec requires specific response structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025–11–03T…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"parts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"…"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"messageId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"msg-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"taskId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task-id"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"artifacts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This took iteration - initially I missed &lt;code&gt;messageId&lt;/code&gt; and &lt;code&gt;taskId&lt;/code&gt; in the status message, causing Telex integration to fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment on Heroku
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Procfile&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web: bin/server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Dynamic Port Binding&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PORT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"8080"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Environment Variables&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku config:set &lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Deploy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push heroku main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Heroku Go buildpack automatically runs &lt;code&gt;go install&lt;/code&gt;, compiles the binary to &lt;code&gt;bin/server&lt;/code&gt;, and the Procfile starts it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Don't Over-Engineer Parsing
&lt;/h3&gt;

&lt;p&gt;My first version had elaborate country/profession dictionaries. Gemini handles this better than any regex or dictionary lookup.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. A2A Protocol Details Matter
&lt;/h3&gt;

&lt;p&gt;Small spec violations (missing &lt;code&gt;messageId&lt;/code&gt;, wrong JSON structure) break integrations. Test with actual A2A clients early.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Prompt Engineering Is Critical
&lt;/h3&gt;

&lt;p&gt;The difference between "suggest migration options" and "provide THE SINGLE BEST option without asking questions" is massive. The second version eliminates back-and-forth.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. LLM Temperature Matters
&lt;/h3&gt;

&lt;p&gt;For structured output, low temperature (default) works better than high creativity settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;I created &lt;code&gt;.http&lt;/code&gt; files for VS Code REST Client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST {{host}}/a2a/planner
Content-Type: application/json
{
 "jsonrpc": "2.0",
 "method": "message/send",
 "params": {
 "message": {
 "role": "user",
 "parts": [{
 "type": "text",
 "text": "I am a nurse from Philippines wanting to move to UK"
 }]
 }
 },
 "id": 1
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made iteration fast - no need to rebuild integrations for every test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live API&lt;/strong&gt;: &lt;a href="https://migration-pathways-agent-ca4e1c945e86.herokuapp.com/a2a/planner" rel="noopener noreferrer"&gt;https://migration-pathways-agent-ca4e1c945e86.herokuapp.com/a2a/planner&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Agent Card&lt;/strong&gt;: &lt;a href="https://migration-pathways-agent-ca4e1c945e86.herokuapp.com/.well-known/agent.json" rel="noopener noreferrer"&gt;https://migration-pathways-agent-ca4e1c945e86.herokuapp.com/.well-known/agent.json&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Example cURL&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://migration-pathways-agent-ca4e1c945e86.herokuapp.com/a2a/planner &lt;span class="se"&gt;\&lt;/span&gt;
 -H &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
 -d &lt;span class="s1"&gt;'{
 "jsonrpc": "2.0",
 "method": "message/send",
 "params": {
 "message": {
 "role": "user",
 "parts": [{
 "type": "text",
 "text": "I am a data scientist from India wanting to move to USA with $10000"
 }]
 }
 },
 "id": 1
 }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Screenshot of the AI Agent on Telex
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54hyyo1300wpt7v8zdxa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54hyyo1300wpt7v8zdxa.png" alt=" " width="800" height="724"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building an AI agent isn't just about calling an LLM API - it's about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choosing the right protocol (A2A for interoperability)&lt;/li&gt;
&lt;li&gt;Crafting precise prompts that eliminate ambiguity&lt;/li&gt;
&lt;li&gt;Structuring responses for both humans and machines&lt;/li&gt;
&lt;li&gt;Deploying reliably with proper error handling
The Migration Pathways Agent demonstrates that with the right architecture, you can build practical, production-ready AI tools that solve real problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href="https://github.com/brainox/immigration-pathways-agent" rel="noopener noreferrer"&gt;github.com/brainox/immigration-pathways-agent&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Questions? Feedback? Hit me up on X  @ObinnaAguwa or try the agent and let me know what visa pathway it suggests for you!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>go</category>
      <category>a2a</category>
    </item>
    <item>
      <title>Getting Started with Pathway</title>
      <dc:creator>Obinna Aguwa</dc:creator>
      <pubDate>Wed, 02 Apr 2025 13:42:36 +0000</pubDate>
      <link>https://dev.to/macmartins/getting-started-with-pathway-49ed</link>
      <guid>https://dev.to/macmartins/getting-started-with-pathway-49ed</guid>
      <description>&lt;p&gt;If you work with real-time data and need a way to process it efficiently, Pathway might be the tool for you. It is designed to help developers handle data streams and build applications that react to changes instantly. This guide will walk you through how to get started and show you how to use some of its key features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Pathway
&lt;/h3&gt;

&lt;p&gt;Before anything else, you need to install Pathway. It requires Python 3.10 or later, so make sure you have the right version installed. Open your terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pathway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all you need to do to get Pathway set up on your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding How Pathway Works
&lt;/h3&gt;

&lt;p&gt;Pathway is built around the idea of processing data as it arrives. Instead of handling data in batches, it continuously updates results as new information comes in. Here are some of the main things you will work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tables&lt;/strong&gt; – These hold your data, similar to a spreadsheet or a pandas dataframe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input Sources&lt;/strong&gt; – These bring data into your Pathway application, such as CSV files, databases, or API streams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformations&lt;/strong&gt; – These let you filter, sort, and modify data to match your needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output Destinations&lt;/strong&gt; – These allow you to save processed data in formats like JSON or send it to another system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these basic ideas in mind, let’s go ahead and build something.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Simple Pathway Application
&lt;/h3&gt;

&lt;p&gt;Here is a small example that reads data from a CSV file, filters it, and writes the results to another file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Import Pathway
&lt;/h4&gt;

&lt;p&gt;Start by creating a Python file and adding this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pathway&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Read Data
&lt;/h4&gt;

&lt;p&gt;Use an input connector to load data from a CSV file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Process the Data
&lt;/h4&gt;

&lt;p&gt;Let’s say you only want rows where the value in the "amount" column is greater than 100. You can do that with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;filtered_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Write the Output
&lt;/h4&gt;

&lt;p&gt;Now, save the filtered data to a JSON Lines file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jsonlines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.jsonl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Run the Program
&lt;/h4&gt;

&lt;p&gt;Save your file and run it using Python. Pathway will process the data and save the filtered results.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;This is just a simple example, but Pathway can do much more. It supports handling data from live streams, integrating with machine learning models, and managing complex transformations. If you want to explore more, check out these resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pathway.com/developers" rel="noopener noreferrer"&gt;Official Documentation&lt;/a&gt;&lt;/strong&gt; – Learn about all the features in detail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/pathwaycom/" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/strong&gt; – See the source code and examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://discord.com/invite/pathway" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt;&lt;/strong&gt; – Connect with other developers using Pathway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you get comfortable with the basics, you can start experimenting with real-time data processing and more advanced use cases. Pathway makes it easier to build applications that react to data changes instantly, and with a bit of practice, you will be able to create powerful solutions for your projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What is DevRel and why are they important?</title>
      <dc:creator>Obinna Aguwa</dc:creator>
      <pubDate>Mon, 17 Mar 2025 22:34:14 +0000</pubDate>
      <link>https://dev.to/macmartins/what-is-devrel-and-why-are-they-important-2727</link>
      <guid>https://dev.to/macmartins/what-is-devrel-and-why-are-they-important-2727</guid>
      <description>&lt;p&gt;Not many people are familiar with the term "DevRel." To be honest, it is still relatively new since there aren’t many people with the job title of DevRel Engineer or Developer.&lt;br&gt;
In this article, I will explain who a DevRel professional is and why they are important.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What is DevRel?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;DevRel stands for Developer Relations. It is a field in tech that focuses on building authentic relationships with developers who use a particular technology. In my experience as a software developer, I tend to develop more interest in technology when I feel fully supported—such as having access to a community of developers who can answer my questions and provide resources to solve my problems. The people responsible for educating and supporting these developers are called DevRel professionals (or simply "DevRels").&lt;/p&gt;

&lt;p&gt;It’s important to note that their role varies depending on a company’s needs. For example, in a tooling company like Microsoft, DevRels might focus on outreach, advocacy, and delivering tech demos or examples to developers. On the other hand, in a company like Google, DevRels might focus on evangelizing new tech offerings in AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The 3 Types of DevRel Roles&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Community builder&lt;/li&gt;
&lt;li&gt;Developer educator&lt;/li&gt;
&lt;li&gt;Developer experience engineer&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Builders&lt;/strong&gt; focus on organizing events, hosting livestreams, managing Discord/Slack communities, and gathering feedback from users. They act as a bridge between the company and its developer audience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Educators&lt;/strong&gt; create blogs, videos, and courses. They also speak at conferences and host workshops. Personally, this is the role that resonates most with me.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Experience Engineers&lt;/strong&gt; aim to make it easier for developers to use a product. They improve documentation, provide useful coding examples and demos, and streamline product integration to ensure a seamless experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Are DevRels Important?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They Enhance Brand Reputation.&lt;/strong&gt;&lt;br&gt;
A brand is shaped by how people perceive it, not necessarily by reality. DevRels are often closer to the developers who use a company’s tools because, more often than not, DevRels were developers themselves. They understand how developers think and can relate to their challenges. When developers find it easier to connect with a product, it invariably improves the company’s reputation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They Improve Product Development.&lt;/strong&gt;&lt;br&gt;
DevRels gathers feedback from conferences, webinars, and direct interactions with developers. This feedback is invaluable for improving product features, fixing bugs, and identifying new business opportunities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They Foster Community Building&lt;/strong&gt;.&lt;br&gt;
By providing platforms for developers to connect, collaborate, and share knowledge, DevRels helps create a more engaged and active ecosystem. Strong communities lead to stronger adoption of technologies and foster innovation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;DevRel professionals play a crucial role in bridging the gap between companies and their developer communities. Whether through education, community engagement, or improving the developer experience, they contribute significantly to the success of a product and the growth of its ecosystem.&lt;/p&gt;

&lt;p&gt;As the tech industry continues to evolve, the importance of DevRel roles will only increase. If you’re passionate about both technology and people, this might just be the perfect career path for you!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
