<?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: Fabiyi Pelumi</title>
    <description>The latest articles on DEV Community by Fabiyi Pelumi (@cipher126).</description>
    <link>https://dev.to/cipher126</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%2F3594860%2F7c3dbffc-1850-4911-a080-b29dc44a674b.png</url>
      <title>DEV Community: Fabiyi Pelumi</title>
      <link>https://dev.to/cipher126</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cipher126"/>
    <language>en</language>
    <item>
      <title>Building a Telex Agent That Summarizes PDFs with FastAPI</title>
      <dc:creator>Fabiyi Pelumi</dc:creator>
      <pubDate>Tue, 04 Nov 2025 01:58:05 +0000</pubDate>
      <link>https://dev.to/cipher126/building-a-telex-agent-that-summarizes-pdfs-with-fastapi-95p</link>
      <guid>https://dev.to/cipher126/building-a-telex-agent-that-summarizes-pdfs-with-fastapi-95p</guid>
      <description>&lt;h2&gt;
  
  
  🧠 Building a Telex Agent That Summarizes PDFs with FastAPI
&lt;/h2&gt;

&lt;p&gt;Telex recently opened up its workflow agents, small independent services that can take messages, perform actions, and respond in real time. I decided to build one from scratch using &lt;strong&gt;FastAPI&lt;/strong&gt;, and it turned into one of the most interesting debugging sessions I've had in a while.&lt;/p&gt;

&lt;p&gt;This post walks through how I built a &lt;strong&gt;Telex A2A (Agent-to-Agent) Summarizer&lt;/strong&gt;, which takes a PDF file URL, extracts the text, and sends back a concise summary all over a JSON-RPC endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ What I Built
&lt;/h2&gt;

&lt;p&gt;The goal was simple:&lt;br&gt;&lt;br&gt;
Whenever a message containing a PDF link hits my agent, it should automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract the text from the PDF.&lt;/li&gt;
&lt;li&gt;Summarize the content.&lt;/li&gt;
&lt;li&gt;Return the summarized text back to Telex as a response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent listens for Telex JSON-RPC events on the endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /a2a/summarize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and expects a payload like this:&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="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="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;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"summarize/pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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="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="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="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;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&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="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&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;"Check out this PDF: https://media.telex.im/sample.pdf"&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="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="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;Once the request arrives, my FastAPI app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detects the PDF URL in the message text.&lt;/li&gt;
&lt;li&gt;Extracts the PDF content using a text extraction service.&lt;/li&gt;
&lt;li&gt;Summarizes it using a custom summarizer.&lt;/li&gt;
&lt;li&gt;Sends the summarized text back to Telex in a properly structured JSON-RPC response.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Here's the basic flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Telex → FastAPI Agent → PDF Extractor → Summarizer → Telex Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each message that hits the &lt;code&gt;/a2a/summarize&lt;/code&gt; route is parsed into a &lt;code&gt;RPCRequest&lt;/code&gt; model.&lt;/p&gt;

&lt;p&gt;After validation, the agent uses &lt;code&gt;extract_text()&lt;/code&gt; to pull text from the file URL, then calls &lt;code&gt;summarize_text()&lt;/code&gt; to generate a concise summary.&lt;/p&gt;

&lt;p&gt;Finally, it constructs a &lt;code&gt;RPCResponse&lt;/code&gt; containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The summarized message.&lt;/li&gt;
&lt;li&gt;Metadata like &lt;code&gt;taskId&lt;/code&gt;, &lt;code&gt;messageId&lt;/code&gt;, and &lt;code&gt;artifactId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A clear "completed" task state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This response is sent back to Telex to be displayed in the workflow logs or UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 The Debugging Story
&lt;/h2&gt;

&lt;p&gt;When I first deployed it, Telex didn't show any response even though my server logs said "Response sent successfully."&lt;/p&gt;

&lt;p&gt;After digging into the issue, I realized my agent was simply too slow.&lt;/p&gt;

&lt;p&gt;Telex's default timeout was 15 seconds, while my PDF extraction and summarization could take longer depending on file size.&lt;/p&gt;

&lt;p&gt;After some collaboration with the Telex devs, the timeout was increased to 60 seconds, and instantly my agent came to life. The summarized response started showing up in the Telex logs.&lt;/p&gt;

&lt;p&gt;It was a satisfying moment watching that JSON come full circle.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; for building the JSON-RPC server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; core language for parsing, processing, and responding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regex&lt;/strong&gt; for detecting Telex media URLs in message parts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF Extractor Service&lt;/strong&gt; handles text extraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summarizer Service&lt;/strong&gt; compresses extracted text into meaningful summaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UUIDs&lt;/strong&gt; to track messages and tasks uniquely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔮 Next Steps
&lt;/h2&gt;

&lt;p&gt;Now that the summarizer agent is working, I'm planning to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add support for multi-file summarization.&lt;/li&gt;
&lt;li&gt;Cache results to improve speed.&lt;/li&gt;
&lt;li&gt;Expose summary statistics (like reading time and keyword extraction).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, I want to make it easier for Telex agents to process large files seamlessly within workflow automations.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building this Telex agent taught me how well-designed the platform's A2A architecture is. It's simple but powerful just JSON-RPC, HTTP, and well-defined structure.&lt;/p&gt;

&lt;p&gt;If you're thinking of building your own Telex agent, start small. Handle one message type, log everything, and iterate. Once your responses show up in the Telex logs, you'll realize how rewarding that little green "success" status can be.&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>automation</category>
      <category>webhooks</category>
    </item>
  </channel>
</rss>
