The HNG Stage 3 task was a big one: build and integrate a "from scratch" AI agent. As a Java developer, I chose my trusted stack: Spring Boot and Google's Gemini API. My goal? A simple agent that could take a job role (like "Backend Developer") and return a list of high-quality interview questions.
I thought it would be a straightforward API. I was wrong.
This is the story of how I built the agent, discovered the "plot twist" of the real A2A protocol, debugged it live, and finally got it working. Here’s how I did it.
Part 1: The "Core Brain" – Just Java and Gemini
Before ever thinking about "agents" or "protocols," I focused on the hardest part first: talking to the Gemini AI. I created a "Core Brain" for my app, a simple GeminiService with one job:
Take a String (like "React Developer").
Build a smart prompt around it.
Send it to the Gemini API and return the AI's answer as a String.
To do this, I built two key components:
GeminiDto.java: A set of Java records that perfectly matched the JSON "contract" that Google's API expects. This let me use Java objects instead of building messy JSON strings.
GeminiService.java: The "worker" class that used Spring's RestTemplate to make the HTTP call. It would package up the GeminiDto request, send it, and parse the GeminiDto response.
At this point, I had a working CommandLineRunner test. I could type a job role into my console and get AI-generated questions back. I thought I was 80% done.
Part 2: The "Plot Twist" – Discovering the Real A2A Protocol
This was the most critical (and frustrating) part of the project. My initial plan was to build a simple controller with an endpoint like @PostMapping("/questions") that just took a simple JSON request.
After deploying and trying to connect to Telex, it failed. Nothing happened.
After digging through logs (and a lot of confusion), I discovered the truth: Telex.im does not use a simple REST API. It requires a formal, complex communication protocol called JSON-RPC 2.0.
This meant my agent had to speak a whole new language. I had to throw out my planned DTOs and controller and start that part again.
Part 3: The "Secretary" – Building the JSON-RPC Front Door
My GeminiService (the "brain") was perfect and didn't need to change. But I needed a new "front door," a "secretary" that could speak this new JSON-RPC language.
This involved building a new set of DTOs and a new controller.
The New Contract (A2ADto.java): I created a new set of Java records that modeled the entire JSON-RPC 2.0 structure Telex expects. This was far more complex, with nested objects for id, method, params, result, status, and artifacts.
The New Controller (AgentController.java): This controller was much smarter. Its job was to be the "translator":
- It received the formal A2ARequest from Telex.
- It navigated the complex JSON to find the user's message.
- It passed that one simple string to my GeminiService (which didn't know or care where the string came from).
- It got the AI's answer.
- It carefully packaged that answer back into the formal A2AResponse structure, with a status, artifacts, and the correct id.
- This design (isolating the "brain" from the "front door") is what saved me. It meant I only had to refactor one part of my app, not the whole thing.
Part 4: Debugging the Deployed Agent (The Final 10%)
I deployed the new code to Render. It worked... sometimes. And sometimes it failed. The Telex logs (which are excellent) showed two new problems.
Problem 1: The JSON Crash
The Log: My app would crash, but only on long conversations. The Cause: Telex sends a lot of history and metadata in its JSON. My A2ADto.java file was strict and would fail if it saw an unexpected field (like kind: "data"). The Fix: I added one annotation to my Part record in A2ADto.java: @JsonIgnoreProperties(ignoreUnknown = true) This told Spring Boot, "Only parse the fields you know (kind, text, data), and just ignore everything else." This made my agent robust.
Problem 2: The Timeout / Partial Message
The Log: The agent would work, but sometimes the response would get cut off or just fail. The Cause: Telex was sending "blocking": false in its request. It was telling my agent, "Don't make me wait for your answer." But my agent (on Render's free tier) was "sleeping" (a "cold start") and needed time to wake up and call Gemini. The Fix: This wasn't a code fix. It was a configuration fix in the Telex UI. I had to tell the Telex Workflow to force a blocking request.
Part 5: The "Final Handshake" – The Workflow JSON
This was the final piece. You don't just paste your URL into a settings box in Telex. You have to "register" your agent by building (or importing) a Workflow JSON.
This JSON file is what tells Telex, "Here is my agent, here is its name, and here is the URL it listens at."
Here is the key part of my final workflow JSON that made it all work:
{
"active": true,
"name": "Interview Agent",
"nodes": [
{
"id": "interview_agent_node",
"name": "Interview Question Agent",
"parameters": {
"blocking": true
},
"type": "a2a/generic-a2a-node",
"typeVersion": 1,
"url": "https://telex-ai-agent-0rby.onrender.com/api/agent/message"
}
],
"short_description": "Generates interview questions for any job role."
}
The two most important lines are:
1. "url": My full, deployed endpoint URL.
- "parameters": { "blocking": true }: The magic line that fixed my timeout errors by forcing Telex to wait for my (sometimes sleepy) Render app.
Conclusion and Key Takeaways
This project was a fantastic challenge that was less about AI and more about system integration and protocol-level debugging.
My key takeaways were:
- Isolate Your Logic: Keep your "brain" (the GeminiService) separate from your "protocol" (the AgentController). It makes refactoring painless.
- Logs Are Your Best Friend: The Telex workflow logs were the only way I could have solved this.
- Beware the Cold Start: Free tiers sleep! I set up a free service called Uptime Robot to ping my /health endpoint every 15 minutes. This keeps my app "warm" and ready, solving the cold start problem for good. 4.Don't Assume: I assumed a simple REST API would be enough. I was wrong, and learning to build the JSON-RPC 2.0 "secretary" was the real task.
In the end, I have a fully functional, deployed, and robust AI agent working live in Telex.
Top comments (0)