<?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: Tobi Awanebi </title>
    <description>The latest articles on DEV Community by Tobi Awanebi  (@bituan).</description>
    <link>https://dev.to/bituan</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%2F1704229%2F83d049b8-7b8b-4b18-9da3-0a807c2b3ba2.png</url>
      <title>DEV Community: Tobi Awanebi </title>
      <link>https://dev.to/bituan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bituan"/>
    <language>en</language>
    <item>
      <title>Developing an A2A-compliant AI Agent with Java, Spring Boot and Spring AI</title>
      <dc:creator>Tobi Awanebi </dc:creator>
      <pubDate>Tue, 04 Nov 2025 12:23:23 +0000</pubDate>
      <link>https://dev.to/bituan/developing-an-a2a-compliant-ai-agent-with-java-spring-boot-and-spring-ai-3l5e</link>
      <guid>https://dev.to/bituan/developing-an-a2a-compliant-ai-agent-with-java-spring-boot-and-spring-ai-3l5e</guid>
      <description>&lt;p&gt;An AI agent refers to a software entity that can perceive, reason, and act autonomously to achieve specific goals using artificial intelligence techniques like natural language processing, machine learning, or reasoning systems.&lt;/p&gt;

&lt;p&gt;I developed an AI agent for &lt;a href="https://telex.im" rel="noopener noreferrer"&gt;Telex&lt;/a&gt; which takes a regex pattern and provides a human-friendly explanation on the type(s) of string matched by that regex pattern. The inspiration for this agent lie in an API I developed just before this, where I had to use regex for some natural language processing (you can check out the project &lt;a href="https://github.com/bituann/string-analyzer-api" rel="noopener noreferrer"&gt;here&lt;/a&gt;). Though I had learnt regex previously, it felt like I was seeing it for the first time. Regex is just like that. So when Telex sought for more AI agents for their platform, I decided to develop this agent.&lt;/p&gt;

&lt;p&gt;Here's how I did it using Java, Spring AI and Spring Boot&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Initial Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Spring Boot Project Initialization
&lt;/h3&gt;

&lt;p&gt;I initialize your project using the &lt;a href="https://start.spring.io" rel="noopener noreferrer"&gt;initializer&lt;/a&gt; provided by Spring. Notice that I included Spring Web and Open AI in the dependencies&lt;/p&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%2Fezwuzxplsr4ljnhnaezc.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%2Fezwuzxplsr4ljnhnaezc.png" alt="intialize spring project" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Set Up API Credentials
&lt;/h3&gt;

&lt;p&gt;In my &lt;code&gt;application.properties&lt;/code&gt; files, I set up Spring AI to use my API credentials (my API key). I got a free Google's Gemini API key using Google AI studio. Here's how my &lt;code&gt;application.properties&lt;/code&gt; file is set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.config.import=classpath:AI.properties

spring.application.name=regexplain

spring.ai.openai.api-key = ${GEMINI_API_KEY}
spring.ai.openai.base-url = https://generativelanguage.googleapis.com/v1beta/openai
spring.ai.openai.chat.completions-path = /chat/completions
spring.ai.openai.chat.options.model = gemini-2.5-pro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line imports the file that contains my API key. It is important that you don't expose your API key to the public. The file is located in the same folder as &lt;code&gt;application.properties&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. First Project Run
&lt;/h3&gt;

&lt;p&gt;Using my package manager(maven), I installed the needed dependencies. Then I ran my main class to be sure that everything works as it should. If you everything right up to this point, yours should run without errors. If you encounter any error, look it up on Google to find a fix.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A2A Request and Response Model
&lt;/h2&gt;

&lt;p&gt;Before I go into the implementation, let's talk a bit on the structure of an A2A-compliant request and response. The A2A protocol adheres to the standard JSON-RPC 2.0 structures for requests and responses.&lt;/p&gt;

&lt;p&gt;All method calls are encapsulated in a request object, which looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  jsonrpc: "2.0"; 
  method: String; 
  id: String | Integer;
  params: Message;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is a bit similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  jsonrpc: "2.0"; 
  id: String | Integer | null;
  result?: Task | Message | null;
  error?: JSONRPCError;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response ID MUST be the same as the request ID.&lt;/p&gt;

&lt;p&gt;For more information on the A2A protocol, check out the &lt;a href="https://a2a-protocol.org/latest/" rel="noopener noreferrer"&gt;A2A protocol docs&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;That is the general structure of the request and response. I developed this agent for use in the Telex platform, so some of my implementation may be specific to Telex.&lt;/p&gt;

&lt;p&gt;Now, to the implementation. I created a folder called &lt;code&gt;model&lt;/code&gt;, where I'll store my models. The request model class called &lt;code&gt;A2ARequest&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class A2ARequest {
    private String id;
    private RequestParamsProperty params;

    public A2ARequest(String id, RequestParamsProperty params) {
        this.id = id;
        this.params = params;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;RequestParamsProperties&lt;/code&gt; class represent the structure of the information contained in &lt;code&gt;params&lt;/code&gt;. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class RequestParamsProperty {
    private HistoryMessage message;
    private String messageId;

    public RequestParamsProperty(HistoryMessage message, String messageId) {
        this.message = message;
        this.messageId = messageId;
    }

    // getters and setter
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;HistoryMessage&lt;/code&gt; class looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HistoryMessage {
    private String kind;
    private String role;
    private List&amp;lt;MessagePart&amp;gt; parts;
    private String messageId;
    private String taskId;

    public HistoryMessage() {}

    public HistoryMessage(String role, List&amp;lt;MessagePart&amp;gt; parts, String messageId, String taskId) {
        this.kind = "message";
        this.role = role;
        this.parts = parts;
        this.messageId = messageId;
        this.taskId = taskId;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annotations are so that spring knows what to include in the JSON representation of the request and response. If a property doesn't exist in the request, it should ignore it and set it to null in the class. If a property is set to null, it shouldn't include it in the response.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MessagePart&lt;/code&gt; class looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MessagePart {
    private String kind;
    private String text;
    private List&amp;lt;MessagePart&amp;gt; data;

    public MessagePart(String kind, String text, List&amp;lt;MessagePart&amp;gt; data) {
        this.kind = kind;
        this.text = text;
        this.data = data;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all the classes needed to represent the request structure received from Telex. Now to create a model for my response, and all supporting classes needed to represent my response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@JsonInclude(JsonInclude.Include.NON_NULL)
public class A2AResponse {
    private final String jsonrpc;
    @JsonInclude(JsonInclude.Include.ALWAYS)
    private String id;
    private Result result;
    private CustomError error;

    public A2AResponse() {
        this.jsonrpc = "2.0";
    }

    public A2AResponse(String id, Result result, CustomError error) {
        this.jsonrpc = "2.0";
        this.id = id;
        this.result = result;
        this.error = error;
    }

    //getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Result&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Result {
    private String id;
    private String contextId;
    private TaskStatus status;
    private List&amp;lt;Artifact&amp;gt; artifacts;
    private List&amp;lt;HistoryMessage&amp;gt; history;
    private String kind;

    public Result() {}

    public Result(String id, String contextId, TaskStatus status, List&amp;lt;Artifact&amp;gt; artifacts, List&amp;lt;HistoryMessage&amp;gt; history, String task) {
        this.id = id;
        this.contextId = contextId;
        this.status = status;
        this.artifacts = artifacts;
        this.history = history;
        this.kind = task;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CustomError&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomError {
    private int code;
    private String message;
    private Map&amp;lt;String, String&amp;gt; data;

    public CustomError(int code, String message, Map&amp;lt;String, String&amp;gt; data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;TaskStatus&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@JsonInclude(JsonInclude.Include.NON_NULL)
public class TaskStatus {
    private String state;
    private Instant timestamp;
    private HistoryMessage message;

    public TaskStatus() {}

    public TaskStatus(String state, Instant timestamp, HistoryMessage message) {
        this.state = state;
        this.timestamp = timestamp;
        this.message = message;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Artifact&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Artifact {
    private String artifactId;
    private String name;
    private List&amp;lt;MessagePart&amp;gt; parts; // come back to review that type

    public Artifact() {}

    public Artifact(String artifactId, String name, List&amp;lt;MessagePart&amp;gt; parts) {
        this.artifactId = artifactId;
        this.name = name;
        this.parts = parts;
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The A2A protocol also includes something called the agent card. I created a model for it also.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AgentCard {
    private String name;
    private String description;
    private String url;
    private Map&amp;lt;String, String&amp;gt; provider;
    private String version;
    private Map&amp;lt;String, Boolean&amp;gt; capabilities;
    private List&amp;lt;String&amp;gt; defaultInputModes;
    private List&amp;lt;String&amp;gt; defaultOutputModes;
    private List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; skills;

    public AgentCard() {
        this.provider = new HashMap&amp;lt;&amp;gt;();
        this.capabilities = new HashMap&amp;lt;&amp;gt;();
        this.skills = new ArrayList&amp;lt;&amp;gt;();
    }

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all for models. Moving on...&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Service Class
&lt;/h2&gt;

&lt;p&gt;What my agent does is to get a regex string and then send it to OpenAI's API with a predefined prompt. The service class handles communicating with OpenAI, sending the prompt and receiving the response. I created another folder called &lt;code&gt;service&lt;/code&gt; which is where my service class resides. This is how I wrote my service class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class RegExPlainService {
    private ChatClient chatClient;

    RegExPlainService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @Tool(name = "regexplain", description = "An agent that explains what type of string a regex pattern matches")
    public String generateResponse(String regex) {
        return chatClient
                .prompt("Give me a simple explanation of the type of string matched by this regex pattern: %s. No validating statements from you. Just straight to the point".formatted(regex))
                .call()
                .content();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service annotation allows Spring Boot to perform a service injection into your controller. The Tool annotation marks the method as an agent tool which can be autonomously called if the agent is to be extended to include that functionality. It's not needed right now, though.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Controller
&lt;/h2&gt;

&lt;p&gt;The controller exposes the agent using REST API. In this case, I have two endpoints, a &lt;code&gt;GET&lt;/code&gt; endpoint and a &lt;code&gt;POST&lt;/code&gt; endpoint. I created my controller in a folder called &lt;code&gt;controller&lt;/code&gt;. This is the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
public class RegExPlainController {
    private final RegExPlainService regexplainService;

    @Autowired
    RegExPlainController (RegExPlainService regexplainService) {
        this.regexplainService = regexplainService;
    }

    @GetMapping("/a2a/agent/regexplain/.well-known/agent.json")
    public ResponseEntity&amp;lt;AgentCard&amp;gt; getAgentCard () {
        AgentCard agentCard = new AgentCard();
        agentCard.setName("regexplain");
        agentCard.setDescription("An agent that provides a simple explanation of the type of string a regex pattern matches");
        agentCard.setUrl("regexplain-production.up.railway.app/api");
        agentCard.setProvider("Bituan", null);
        agentCard.setVersion("1.0");
        agentCard.setCapabilities(false, false, false);
        agentCard.setDefaultInputModes(List.of("text/plain"));
        agentCard.setDefaultOutputModes(List.of("application/json", "text/plain"));
        agentCard.setSkill("skill-001", "Explain Regex", "Provides a simple explanation of the type of string a regex pattern matches",
                List.of("text/plain"), List.of("text/plain"), List.of());

        return ResponseEntity.ok(agentCard);
    }

    @PostMapping("/a2a/agent/regexplain")
    public ResponseEntity&amp;lt;A2AResponse&amp;gt; explainRegex (@RequestBody A2ARequest request) {
        String regexRequest;
        String responseText;

        // return 403 if parameter is invalid
        try {
            regexRequest = request.getParams().getMessage().getParts().get(0).getText();
        } catch (Exception e) {
            CustomError error = new CustomError(-32603, "Invalid Parameter", Map.of("details", e.getMessage()));
            A2AResponse errorResponse = new A2AResponse(null, null,  error);
            return ResponseEntity.status(HttpStatusCode.valueOf(403)).body(errorResponse);
        }

        // return error 500 if call to service fails
        try {
            responseText = regexplainService.generateResponse(regexRequest);
        } catch (Exception e) {
            CustomError error = new CustomError(-32603, "Internal Error", Map.of("details", e.getMessage()));
            A2AResponse errorResponse = new A2AResponse(null, null,  error);
            return ResponseEntity.internalServerError().body(errorResponse);
        }

        // response building
        A2AResponse response = new A2AResponse();
        response.setId(request.getId());

        // response building -&amp;gt; result building
        Result result = new Result();
        result.setId(UUID.randomUUID().toString());
        result.setContextId(UUID.randomUUID().toString());
        result.setKind("task");

        // response building -&amp;gt; result building -&amp;gt; status building
        TaskStatus status = new TaskStatus();
        status.setState("completed");
        status.setTimestamp(Instant.now());

        // response building -&amp;gt; result building -&amp;gt; status building -&amp;gt; message building
        HistoryMessage message = new HistoryMessage();
        message.setRole("agent");
        message.setParts(List.of(new MessagePart("text", responseText, null)));
        message.setKind("message");
        message.setMessageId(UUID.randomUUID().toString());

        // response building -&amp;gt; result building -&amp;gt; status building contd
        status.setMessage(message);

        // response building -&amp;gt; result building -&amp;gt; artifact building
        List&amp;lt;Artifact&amp;gt; artifacts = new ArrayList&amp;lt;&amp;gt;();
        Artifact artifact = new Artifact();
        artifact.setArtifactId(UUID.randomUUID().toString());
        artifact.setName("regexplainerResponse");
        artifact.setParts(List.of(new MessagePart("text", responseText, null)));
        artifacts.add(artifact);


        //response building -&amp;gt; result building -&amp;gt; history building
        List&amp;lt;HistoryMessage&amp;gt; history = new ArrayList&amp;lt;&amp;gt;();

        //response building -&amp;gt; result building contd
        result.setStatus(status);
        result.setArtifacts(artifacts);
        result.setHistory(history);

        // response building contd
        response.setResult(result);

        return ResponseEntity.ok(response);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;GET&lt;/code&gt; endpoint uses a route part of the A2A protocol standard for getting the agent card. The agent card is a description of the agent and what it can do.&lt;br&gt;
The &lt;code&gt;POST&lt;/code&gt; endpoint takes an A2A-compliant request and executes the agent, before returning an appropriate response.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

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

&lt;p&gt;That's it. That's how I wrote Regexplain.&lt;br&gt;
With this, you can build your AI agent from scratch and make it A2A-compliant. Or, at least, I hope this has given you some insight on how to go about developing your A2A-compliant AI agent in Java. I also wrote about how to integrate this agent in Telex. You can read about it &lt;a href="https://dev.to/bituan/integrating-a2a-protocol-ai-agents-built-in-java-with-telex-1ea8"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;That's all for now, thanks for reading. Bye!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>java</category>
      <category>springai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Integrating A2A Protocol AI Agents Built In Java with Telex</title>
      <dc:creator>Tobi Awanebi </dc:creator>
      <pubDate>Mon, 03 Nov 2025 22:41:31 +0000</pubDate>
      <link>https://dev.to/bituan/integrating-a2a-protocol-ai-agents-built-in-java-with-telex-1ea8</link>
      <guid>https://dev.to/bituan/integrating-a2a-protocol-ai-agents-built-in-java-with-telex-1ea8</guid>
      <description>&lt;p&gt;Telex is a collaboration workspace where modern organizations pair human insight with intelligent agents to move faster, stay aligned, and execute at scale. It is built for fluid communication like Slack, but also adds AI coworkers into the conversation that don’t simply answer questions but take action. It's just like Slack, but for education and bootcamps.&lt;/p&gt;

&lt;p&gt;In this article, I will show you how to integrate your AI agents with the &lt;a href="https://telex.im" rel="noopener noreferrer"&gt;Telex&lt;/a&gt; platform. This article is especially for those who are not using Mastra for agent deployment. I assume you have developed and deployed your AI agent already. If you haven't go ahead and do so now. &lt;a href="https://dev.to/bituan/developing-an-a2a-compliant-ai-agent-with-java-spring-boot-and-spring-ai-3l5e"&gt;This article&lt;/a&gt; talks about the specific AI agent I developed for Telex so that Java developers can have a guide on doing so (You can view the AI agent itself on Telex &lt;a href="https://telex.im/telex-ai-intergration/home/colleagues/019a476d-2863-7ee9-aba0-f56ed230632c/019a476d-0eae-7ee8-853e-c65ca3d5b711" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For now, let's see how to integrate with Telex.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create an AI co-Worker
&lt;/h2&gt;

&lt;p&gt;Head over to your Telex dashboard. You would notice a number of things, one of which is the sidebar on the left of the screen. Under the list of AI colleagues, you will see the option to add a new colleague. Click on it. &lt;/p&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%2F18939myfiq0i0pneeidi.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%2F18939myfiq0i0pneeidi.png" alt="Form for creating a new AI co-worker" width="637" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, fill the form that shows up (check the picture above). Ensure to set the visibility to public. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure the co-worker's workflow
&lt;/h2&gt;

&lt;p&gt;After creating it, you will see the name of the worker you just created at the top of the chat screen, and a chat screen. Click on the name of the worker, and on the sidebar that appears on the right, select "Configure Workflow".&lt;/p&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%2Fa06letr422h4f3ep57fl.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%2Fa06letr422h4f3ep57fl.png" alt="Configure workflow screen" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Add a task". Change the view to JSON. You will be using a JSON object to configure the workflow of your co-worker. Your co-worker makes use of your AI agent to carry out its task. This is a template workflow JSON that you can follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "active": true,
  "category": "utilities",
  "description": "An agent that explains what type of string a regex pattern matches",
  "id": "c65ca3d5b711",
  "long_description": "Your job is to explain, in very simple terms, the type of string that a regex pattern matches. You are to ask for a regular expression from the user. When a user sends a regular expression or asks what a particular regular expression does, provide the explanation using the node provided. If the string passed to you contains anything aside from a regular expression, extract only the regular expression. Use only the regular expression from the most recent text sent by the user. Use the regexplain tool to get the string that matches the pattern. Do not respond by yourself, use the node provided. If you are unable to use the node, then say you can't provide an explanation right now. Don't keep message history",
  "name": "bituan_agent",
    "nodes": [
    {
        "id": "regexplain",
        "name": "Regex Explainer",
        "type": "a2a/custom-a2a-node",
        "typeVersion": 1,
        "position": [
        800,
        -100
        ],
        "url": "https://regexplain-production.up.railway.app/a2a/agent/regexplain"
    }
  ],
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "short_description": "take a regex pattern and return a short description of the string it matches"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the JSON object in the field provided and change some of the properties to match your agent. The category, descriptions, id, name, node-id, node-name, node-url are all properties you should change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Testing and logs
&lt;/h2&gt;

&lt;p&gt;Save the workflow and go test it out in the chat section. Check the logs for more information on what's going on in the background. The logs for a specific co-worker can be found at &lt;code&gt;https://api.telex.im/agent-logs/{your-coworker-uuid}.txt&lt;/code&gt;&lt;br&gt;
To get your coworker UUID, send at least one message to your co-worker. Look at the URL of your co-worker, you will see something like this:&lt;br&gt;
&lt;code&gt;https://telex.im/telex-ai-intergration/home/colleagues/{UUID-1}/{UUID-2}&lt;/code&gt;. The first UUID on the URL (UUID-1) is your co-worker UUID.&lt;/p&gt;

&lt;p&gt;With that, your co-worker should be up and running, and it should make requests to your AI agent, and receiving appropriate responses. This interaction can be seen in the logs. Now you have all you need to integrate you AI agent with &lt;a href="https://telex.im" rel="noopener noreferrer"&gt;Telex&lt;/a&gt;. Go out there and build!&lt;/p&gt;

&lt;p&gt;That's all for now. See you in my next post!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>hnginternship</category>
      <category>tutorial</category>
      <category>telex</category>
    </item>
    <item>
      <title>My First Attempt at Backend Development</title>
      <dc:creator>Tobi Awanebi </dc:creator>
      <pubDate>Sat, 29 Jun 2024 16:29:33 +0000</pubDate>
      <link>https://dev.to/bituan/my-first-attempt-at-backend-development-2gnk</link>
      <guid>https://dev.to/bituan/my-first-attempt-at-backend-development-2gnk</guid>
      <description>&lt;p&gt;I've always loved logical thinking, so I wasn't exactly surprised that I was drawn to programming. As with most beginners, I started with frontend programming, and while it's nice and interesting in its own way, it didn't really appeal to me. You know, all I seemed to do was design stuff with code. Eventually, I got to know about backend programming, where all the logic takes place and I fell in love immediately. Even though that's the case, I haven't exactly had the chance to delve into it properly.&lt;/p&gt;

&lt;p&gt;However, a few months ago, I had to try my hands at it for a school project. What I had to do was relatively simple: Develop a REST API that performs CRUD operations on a MySQL database which stores stock data. It was a straightforward task, but there was one very slight problem; I had no idea how to go about it. Here's what I did to work around the problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, I made research on what Python framework would be best for me to use. I came up with a shortlist of about 5 frameworks, but after comparing and contrasting, I decided on Flask&lt;/li&gt;
&lt;li&gt;After deciding, I had to overcome the learning curve. YouTube proved indispensable. I got the basics down in a week, and then I got to work&lt;/li&gt;
&lt;li&gt;I also learned how to connect a flask app to an SQL database. Thankfully, I had taken a course on database design and management, so I could handle the database itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And so I completed the project, getting a distinction while I was at it.&lt;/p&gt;

&lt;p&gt;As I made progress on the project,  I came to a realization all over again (a realization I was always reminded of in school): &lt;em&gt;&lt;strong&gt;as long as you're open to learning, then you can carry out any task, no matter how unfamiliar and challenging it seems at first&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I've come across an &lt;a href="//hng.tech/internship"&gt;internship program&lt;/a&gt; organized by HNG. It's an 8-week training boot camp that is not for beginners. However, that doesn't mean you can't try it out as a beginner. I'm excited and I feel up to the challenge. &lt;/p&gt;

&lt;p&gt;Remember that realization I got? That was one my motivating factors in applying for HNG internship. The second motivating factor was the fact that the HNG internship is task based, so no one is spoon-feeding you. I do not have much knowledge on backend development, but with the multiple projects I will have to carry out, I'm sure to become a well-rounded backend developer. I'm really excited to take on this challenge.&lt;/p&gt;

&lt;p&gt;I really look forward to starting, and if you love a challenge like I do, then come join me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS: If you're a beginner and you're scared, you can pay for &lt;a href="//hng.tech/premium"&gt;HNG premium&lt;/a&gt; at an incredibly affordable rate. You'd have many resources to take you through.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>backenddevelopment</category>
      <category>python</category>
      <category>hnginternship</category>
    </item>
  </channel>
</rss>
