<?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: Ajit</title>
    <description>The latest articles on DEV Community by Ajit (@ajitnk2006).</description>
    <link>https://dev.to/ajitnk2006</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%2F1214886%2F4def6a73-9fa4-4fa4-a91d-b4465bb62077.png</url>
      <title>DEV Community: Ajit</title>
      <link>https://dev.to/ajitnk2006</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ajitnk2006"/>
    <language>en</language>
    <item>
      <title>I Used an AI "Skill" to Audit My CloudFormation Stack — Found a Broken Alarm Running for 3 Months</title>
      <dc:creator>Ajit</dc:creator>
      <pubDate>Wed, 06 May 2026 05:30:43 +0000</pubDate>
      <link>https://dev.to/ajitnk2006/i-used-an-ai-skill-to-audit-my-cloudformation-stack-found-a-broken-alarm-running-for-3-months-1ocn</link>
      <guid>https://dev.to/ajitnk2006/i-used-an-ai-skill-to-audit-my-cloudformation-stack-found-a-broken-alarm-running-for-3-months-1ocn</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Kiro CLI has a feature called "skills" — domain-specific expertise packages you can load on demand. I loaded the aws-cloudformation skill to validate my production Spot Fleet template. It found 4 critical issues including a CloudWatch alarm that literally never worked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Situation
&lt;/h3&gt;

&lt;p&gt;I run a development environment on AWS Spot instances — Kiro CLI, VS Code Server, persistent EBS, the works. The CloudFormation stack has been deployed since February 2026. It's been updated once, runs daily, and I considered it production-ready.&lt;/p&gt;

&lt;p&gt;I was about to upgrade stack  and wanted to validate my base template first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task
&lt;/h3&gt;

&lt;p&gt;Verify whether my "security-hardened" template actually follows CloudFormation best practices before using it as the foundation for upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Action
&lt;/h3&gt;

&lt;p&gt;Step 1 — Discover the skill:&lt;br&gt;
search_documentation("CloudFormation deployment", topics=["agent_skills"])&lt;/p&gt;

&lt;p&gt;This returned 5 relevant skills. I picked aws-cloudformation.&lt;/p&gt;

&lt;p&gt;Step 2 — Load the skill:&lt;br&gt;
retrieve_skill("aws-cloudformation")&lt;/p&gt;

&lt;p&gt;What I got back wasn't generic advice. It was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A structured 10-step authoring checklist&lt;/li&gt;
&lt;li&gt;3-layer validation pipeline (syntax → security → pre-deploy)&lt;/li&gt;
&lt;li&gt;Troubleshooting SOPs for failed stacks&lt;/li&gt;
&lt;li&gt;Decision frameworks for template vs environment fixes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 3 — Load the reference SOP:&lt;br&gt;
retrieve_skill("aws-cloudformation", file="references/author-cloudformation-best-practices.script.md")&lt;/p&gt;

&lt;p&gt;This gave me the detailed checklist: resource naming, parameter design, security defaults, deletion policies, cross-stack references, conditions, outputs.&lt;/p&gt;

&lt;p&gt;Step 4 — Apply it to my template:&lt;/p&gt;

&lt;p&gt;I asked Kiro CLI to review CFN yaml against the skill's checklist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;4 critical, 5 recommended, 1 strict finding.&lt;/p&gt;

&lt;p&gt;Here's what hit hardest:&lt;/p&gt;

&lt;h4&gt;
  
  
  🔴 Critical #1: Broken CloudWatch Alarm (3 months undetected)
&lt;/h4&gt;

&lt;p&gt;yaml&lt;br&gt;
HighCPUAlarm:&lt;br&gt;
  Dimensions:&lt;br&gt;
    - Name: InstanceId&lt;br&gt;
      Value: !Ref SpotFleetRequest  # ← This is a Fleet ID, not an Instance ID&lt;/p&gt;

&lt;p&gt;My "cryptomining detection" alarm was monitoring a dimension that doesn't exist. It never evaluated. Never fired. I had zero protection for 3 months while thinking I was&lt;br&gt;
covered.&lt;/p&gt;

&lt;p&gt;Fix: Reference the actual instance ID (requires a Lambda or instance self-registration pattern since Spot Fleet instances are dynamic).&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are "Skills" Exactly?
&lt;/h3&gt;

&lt;p&gt;They're not prompts. They're not RAG documents. They're structured domain expertise packages containing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Workflows&lt;/td&gt;
&lt;td&gt;Step-by-step procedures with decision points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checklists&lt;/td&gt;
&lt;td&gt;Deterministic validation (like the 10-step authoring review)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SOPs&lt;/td&gt;
&lt;td&gt;Standard operating procedures for troubleshooting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decision trees&lt;/td&gt;
&lt;td&gt;"If X, do Y; if Z, do W" frameworks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reference files&lt;/td&gt;
&lt;td&gt;Architecture docs, schemas, examples&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CloudFormation skill has SOPs for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authoring with secure defaults&lt;/li&gt;
&lt;li&gt;3-layer pre-deployment validation (cfn-lint → cfn-guard → change set)&lt;/li&gt;
&lt;li&gt;Troubleshooting failed stacks (using describe-events --filters FailedEvents=true)&lt;/li&gt;
&lt;li&gt;Resource property lookup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key insight: The skill told me to use describe-events (newer API with filter support) instead of describe-stack-events (legacy, no filters). I didn't know this API existed.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use Skills in Kiro CLI
&lt;/h3&gt;

&lt;p&gt;bash&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Search for relevant skills
&lt;/h1&gt;

&lt;h1&gt;
  
  
  (you can't guess skill names — they must be discovered)
&lt;/h1&gt;

&lt;p&gt;search_documentation("your task description", topics=["agent_skills"])&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Load the skill
&lt;/h1&gt;

&lt;p&gt;retrieve_skill("exact-skill-name-from-search")&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Load reference files if the skill links to them
&lt;/h1&gt;

&lt;p&gt;retrieve_skill("skill-name", file="references/some-sop.md")&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Apply — ask the AI to use the loaded expertise
&lt;/h1&gt;

&lt;p&gt;"Review my template against the authoring checklist"&lt;br&gt;
"Troubleshoot my failed stack using the SOP"&lt;br&gt;
"Validate before I deploy"&lt;/p&gt;

&lt;p&gt;Available skills I found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aws-cloudformation — authoring, validation, troubleshooting&lt;/li&gt;
&lt;li&gt;launching-ec2-instance-with-best-practices — secure EC2 launches&lt;/li&gt;
&lt;li&gt;creating-production-vpc-multi-az — VPC design&lt;/li&gt;
&lt;li&gt;creating-ec2-image-builder-pipeline — AMI automation&lt;/li&gt;
&lt;li&gt;aws-cdk — CDK patterns and deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lessons Learned
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;"It works" ≠ "It's correct." My stack ran fine for 3 months with a broken alarm. Functional doesn't mean secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate infrastructure like you lint code. We wouldn't ship code without tests. Why do we ship CloudFormation without a structured review?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI skills &amp;gt; AI chat. A general "review my template" prompt gives generic advice. A loaded skill applies a deterministic, comprehensive checklist. The difference is like&lt;br&gt;
asking a random person vs. asking a CloudFormation specialist with a clipboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The scariest bugs are silent ones. A broken alarm doesn't throw errors. It just... doesn't protect you.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The skill doesn't just find problems — it prevents them in new templates.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudformation</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>The Model Is the Brain. The Harness Is the Body. Here's Why That Matters</title>
      <dc:creator>Ajit</dc:creator>
      <pubDate>Mon, 04 May 2026 05:18:31 +0000</pubDate>
      <link>https://dev.to/aws-builders/the-model-is-the-brain-the-harness-is-the-body-heres-why-that-matters-2961</link>
      <guid>https://dev.to/aws-builders/the-model-is-the-brain-the-harness-is-the-body-heres-why-that-matters-2961</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built the same browser agent twice — once with 500 lines of Python, once with 7 lines of JSON. The second one took 5 minutes. The agent harness layer is becoming the real competitive advantage, not the model.&lt;/p&gt;

&lt;p&gt;Last month, I built a browser automation agent. Playwright. Custom orchestration. Login handlers. Error retries. Session management. React-aware form filling. Anti-detection scripts. &lt;strong&gt;500+ lines of Python.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This week, I built the same thing:&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;"model"&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;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"modelId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us.anthropic.claude-sonnet-4-6"&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;"tools"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agentcore_browser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"browser"&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;"systemPrompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a web browsing assistant."&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;Deploy. Invoke. It browses websites, extracts data, fills forms. &lt;strong&gt;Seven lines. Zero orchestration code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But here's the thing most people miss: &lt;strong&gt;I kept both versions.&lt;/strong&gt; And that's the real insight.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changed (and What Didn't)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;500-Line Script&lt;/th&gt;
&lt;th&gt;7-Line Harness&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it does&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates a specific multi-site workflow&lt;/td&gt;
&lt;td&gt;Browses any website, extracts info&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;How it decides&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;I wrote every step&lt;/td&gt;
&lt;td&gt;AI decides the steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost per run&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0 (Playwright, local)&lt;/td&gt;
&lt;td&gt;~$0.10-0.50 (Bedrock tokens)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;95%+ (deterministic)&lt;/td&gt;
&lt;td&gt;~80% (AI reasoning varies)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only does what I coded&lt;/td&gt;
&lt;td&gt;Handles any browsing task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Time to build&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3 days of debugging&lt;/td&gt;
&lt;td&gt;5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The 500-line script is better for its specific job.&lt;/strong&gt; It runs faster, cheaper, and more reliably. Because it doesn't need AI — the steps are known.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 7-line harness is better for everything else.&lt;/strong&gt; Research tasks. Data extraction from unfamiliar sites. Competitive analysis. Anything where the steps aren't known in advance.&lt;/p&gt;

&lt;p&gt;This is my POV: &lt;strong&gt;deterministic + AI is the right architecture.&lt;/strong&gt; Don't use a $0.03/call model to click a button you can click with Playwright for free. But don't write 500 lines of Playwright when 7 lines of config can handle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Harness Is the New Battleground
&lt;/h2&gt;

&lt;p&gt;Everyone's talking about which model is best. Claude vs GPT vs Gemini. Benchmarks. Context windows. Reasoning scores.&lt;/p&gt;

&lt;p&gt;That conversation is becoming irrelevant.&lt;/p&gt;

&lt;p&gt;Models are commoditizing. Claude Sonnet 4.6 and GPT-5.5 are both "good enough" for most agent tasks. The real question is: &lt;strong&gt;what wraps around the model to make it actually work in production?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the harness — the orchestration loop, tool execution, memory, security, compute isolation. And every cloud provider is racing to own it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Harness Product&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AgentCore Harness&lt;/td&gt;
&lt;td&gt;Preview (Apr 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bedrock Managed Agents (OpenAI-specific)&lt;/td&gt;
&lt;td&gt;Limited Preview&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gemini Enterprise Agent Platform&lt;/td&gt;
&lt;td&gt;GA (Apr 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Azure AI Agent Service&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Salesforce&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agentforce&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the container orchestration war all over again. In 2015, everyone had containers. The question was who manages running them. Kubernetes won, and whoever controlled K8s controlled where workloads ran.&lt;/p&gt;

&lt;p&gt;In 2026, everyone has models. The question is who manages running agents. &lt;strong&gt;Whoever controls the harness controls the next decade of cloud spend.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How AgentCore Harness Works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You (prompt) → AgentCore Harness → Bedrock Model (reasoning)
                    ↓                      ↓
              Firecracker microVM    Tool selection
              (isolated per session)       ↓
                    ↓              AgentCore Browser / Shell / Code
              Persistent memory    
              (across sessions)    
                    ↓
              Streamed response → You
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What AWS handles: compute, orchestration loop, tool invocation, memory, auth, observability.&lt;br&gt;
What you handle: a JSON config and a prompt.&lt;/p&gt;

&lt;p&gt;Each session runs in its own &lt;strong&gt;Firecracker microVM&lt;/strong&gt; — the same isolation technology behind Lambda. Not a container. A VM. One session can't see another's data, cookies, or credentials.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started (I Actually Ran This)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install CLI&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @aws/agentcore@preview

&lt;span class="c"&gt;# Create project&lt;/span&gt;
agentcore create &lt;span class="nt"&gt;--name&lt;/span&gt; browseragent &lt;span class="nt"&gt;--model-provider&lt;/span&gt; bedrock
&lt;span class="nb"&gt;cd &lt;/span&gt;browseragent

&lt;span class="c"&gt;# Add browser tool&lt;/span&gt;
agentcore add tool &lt;span class="nt"&gt;--harness&lt;/span&gt; browseragent &lt;span class="nt"&gt;--type&lt;/span&gt; agentcore_browser &lt;span class="nt"&gt;--name&lt;/span&gt; browser

&lt;span class="c"&gt;# Set target account + region&lt;/span&gt;
&lt;span class="c"&gt;# Edit agentcore/aws-targets.json: [{"name":"default","region":"us-west-2","account":"YOUR_ACCOUNT"}]&lt;/span&gt;

&lt;span class="c"&gt;# Deploy (~3 min)&lt;/span&gt;
agentcore deploy &lt;span class="nt"&gt;--yes&lt;/span&gt;

&lt;span class="c"&gt;# Use it&lt;/span&gt;
agentcore invoke &lt;span class="nt"&gt;--harness&lt;/span&gt; browseragent &lt;span class="nt"&gt;--stream&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--prompt&lt;/span&gt; &lt;span class="s2"&gt;"Go to example.com and describe what you see"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output from my actual run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🔧 Tool: browser
⚡ 6005 in · 110 out · 2.2s
Here's what's on the page at example.com:
### Example Domain
The page contains: "Example Domain" heading, body text about documentation use,
and a "Learn more" link to IANA documentation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real. Not a demo. Not a screenshot from someone else's blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Considerations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;What I Found&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No harness charge. You pay for Bedrock tokens + Browser session time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Regions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;us-west-2, us-east-1, eu-central-1, ap-southeast-2 (preview)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Any Bedrock model, plus OpenAI and Gemini. Switch mid-session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Firecracker microVM isolation, IAM execution role, Cedar policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Limitation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Preview — not for production workloads yet&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Gotcha I hit:&lt;/strong&gt; The harness execution role needs &lt;code&gt;bedrock:Converse&lt;/code&gt; and &lt;code&gt;bedrock:ConverseStream&lt;/code&gt; permissions, plus &lt;code&gt;aws-marketplace:ViewSubscriptions&lt;/code&gt; for 3P models. The default CDK policy only includes &lt;code&gt;bedrock:InvokeModel&lt;/code&gt;. I had to add permissions manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to Use Harness
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic automation&lt;/strong&gt; (same steps every time) → Playwright. Cheaper, faster, more reliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex multi-agent workflows&lt;/strong&gt; → Strands Agents SDK with AgentCore Runtime. More control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Existing framework investment&lt;/strong&gt; (LangChain/CrewAI) → Use AgentCore tools standalone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production workloads&lt;/strong&gt; → Wait for GA. It's preview.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;The model is the brain. The harness is the body. Most teams are spending all their time picking the brain and hand-building the body from scratch every time.&lt;/p&gt;

&lt;p&gt;AgentCore Harness lets you stop building bodies and start building solutions. For 80% of agent use cases, config beats code. For the other 20%, write code — but use the harness infrastructure underneath.&lt;/p&gt;

&lt;p&gt;The teams still hand-coding agent orchestration loops are building technical debt. The same way teams hand-coding REST APIs built technical debt before API Gateway existed.&lt;/p&gt;

&lt;p&gt;The question isn't whether to adopt managed agent infrastructure. It's whether you'll be building on it — or competing against someone who already is.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ajit NK — AWS Community Builder, APN FasTrack Partner. Building AI agent solutions at CloudNestle.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"The model is the brain. The harness is the body. I build the body."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;📚 &lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html" rel="noopener noreferrer"&gt;AgentCore Harness docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/04/agentcore-new-features-to-build-agents-faster/" rel="noopener noreferrer"&gt;What's New announcement (Apr 22, 2026)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://strandsagents.com" rel="noopener noreferrer"&gt;Strands Agents SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>aws</category>
      <category>ai</category>
      <category>agents</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How I Track 44 New AWS Repos Per Week Automatically with EventBridge, Bedrock, and FAISS</title>
      <dc:creator>Ajit</dc:creator>
      <pubDate>Wed, 01 Apr 2026 09:38:28 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-i-track-44-new-aws-repos-per-week-automatically-with-eventbridge-bedrock-and-faiss-ke8</link>
      <guid>https://dev.to/aws-builders/how-i-track-44-new-aws-repos-per-week-automatically-with-eventbridge-bedrock-and-faiss-ke8</guid>
      <description>&lt;p&gt;AWS publishes new sample repos almost daily — reference architectures, agent patterns, CDK constructs, security blueprints — spread across 5 different GitHub organizations.&lt;/p&gt;

&lt;p&gt;Most developers never see them until weeks later.&lt;/p&gt;

&lt;p&gt;I built a system that catches them the same day. Here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;AWS maintains 9,657+ repos across these orgs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;aws-samples&lt;/strong&gt; (8,044 repos)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;awslabs&lt;/strong&gt; (992 repos)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-ia&lt;/strong&gt; (234 repos)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-solutions&lt;/strong&gt; (153 repos)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-solutions-library-samples&lt;/strong&gt; (234 repos)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When AWS publishes a new repo — say, a production-ready Bedrock AgentCore sample or a CDK construct for EKS — it's buried. GitHub search doesn't surface it. Google takes days to index it. By the time you find it, someone else already built on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Auto-Indexing Pipeline
&lt;/h2&gt;

&lt;p&gt;I built AWS Solution Finder with a twice-daily auto-indexing pipeline that detects and classifies new repos automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;EventBridge (cron: 2 AM + 2 PM UTC daily)&lt;br&gt;
   ↓&lt;br&gt;
5 separate rules (one per org)&lt;br&gt;
   ↓&lt;br&gt;
Indexer Lambda (Docker, Python 3.12, 3GB, 15-min timeout)&lt;br&gt;
   ↓&lt;br&gt;
For each org:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch ALL repos from GitHub API (paginated)&lt;/li&gt;
&lt;li&gt;Compare with master index in S3 → find NEW + REMOVED repos&lt;/li&gt;
&lt;li&gt;Classify new repos with Bedrock Nova Pro (22 metadata fields)&lt;/li&gt;
&lt;li&gt;Generate Titan Embed v2 embeddings (1024-dim)&lt;/li&gt;
&lt;li&gt;Incrementally update FAISS index&lt;/li&gt;
&lt;li&gt;Save to S3 + publish new Lambda version&lt;/li&gt;
&lt;li&gt;Write run record to DynamoDB&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The 22 Metadata Fields
&lt;/h3&gt;

&lt;p&gt;Every repo gets classified by Bedrock Nova Pro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solution type, competency area, AWS services used&lt;/li&gt;
&lt;li&gt;Primary/secondary language, deployment tools&lt;/li&gt;
&lt;li&gt;Cost range, setup time, complexity&lt;/li&gt;
&lt;li&gt;Business value, target audience, freshness status&lt;/li&gt;
&lt;li&gt;Agentic capabilities (yes/no/partial)&lt;/li&gt;
&lt;li&gt;And more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what makes search actually useful — you're not just matching keywords, you're matching intent against structured metadata.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safety Guards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If &amp;gt;50% of repos would be removed in a single run → &lt;strong&gt;blocked&lt;/strong&gt; (likely GitHub API error)&lt;/li&gt;
&lt;li&gt;If GitHub returns 0 repos → master index NOT updated&lt;/li&gt;
&lt;li&gt;Ghost repo detection: repos in FAISS but not on GitHub get cleaned up&lt;/li&gt;
&lt;li&gt;Rate limiting on GitHub API calls (1 sec between classifications)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The New Feature: "New Repos This Week"
&lt;/h2&gt;

&lt;p&gt;Today I shipped a badge on the search page showing repos added in the last 7 days:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🆕 &lt;strong&gt;44 new repos this week&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Grouped by org (aws-samples, awslabs, etc.)&lt;/li&gt;
&lt;li&gt;Direct GitHub links for each&lt;/li&gt;
&lt;li&gt;Rolling 7-day window, updated twice daily&lt;/li&gt;
&lt;/ul&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%2Fh4cr3c31z8h6jv2lg0wj.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%2Fh4cr3c31z8h6jv2lg0wj.png" alt=" " width="800" height="315"&gt;&lt;/a&gt;&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%2Ftd49qdpmmfktkljorytc.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%2Ftd49qdpmmfktkljorytc.png" alt=" " width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives users a reason to come back daily — not just when they need to search.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scheduling&lt;/td&gt;
&lt;td&gt;Amazon EventBridge (5 rules, twice daily)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compute&lt;/td&gt;
&lt;td&gt;AWS Lambda (Docker, Python 3.12, 3GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Classification&lt;/td&gt;
&lt;td&gt;Amazon Bedrock Nova Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embeddings&lt;/td&gt;
&lt;td&gt;Amazon Bedrock Titan Embed v2 (1024-dim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector Search&lt;/td&gt;
&lt;td&gt;FAISS (IndexFlatL2, in-memory)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Amazon S3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit Trail&lt;/td&gt;
&lt;td&gt;Amazon DynamoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IaC&lt;/td&gt;
&lt;td&gt;AWS CDK (TypeScript)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Total cost for the indexing pipeline: almost nothing. The Lambda runs for ~5 minutes twice a day. Bedrock calls are only for NEW repos (not re-classifying existing ones).&lt;/p&gt;

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

&lt;p&gt;The 🆕 badge is live now. Free to try — 3 searches without registration.&lt;/p&gt;

&lt;p&gt;→ &lt;a href="https://awssolutionfinder.solutions.cloudnestle.com/search?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=new-repos-feature" rel="noopener noreferrer"&gt;awssolutionfinder.solutions.cloudnestle.com/search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What AWS repos have you discovered recently that more people should know about?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by Ajit NK — AWS Community Builder (Dev Tools). Building AI-powered developer tools at CloudNestle.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Search 10,000+ AWS GitHub Repos in 10 Seconds</title>
      <dc:creator>Ajit</dc:creator>
      <pubDate>Tue, 31 Mar 2026 12:51:14 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-i-search-10000-aws-github-repos-in-10-seconds-4hi2</link>
      <guid>https://dev.to/aws-builders/how-i-search-10000-aws-github-repos-in-10-seconds-4hi2</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every AWS developer knows this pain: you need a reference architecture or sample code, and you end up with 47 browser tabs open across GitHub, AWS docs, Stack Overflow, and random blog posts from 2019.&lt;/p&gt;

&lt;p&gt;GitHub search gives you 2,000 results with zero context. ChatGPT confidently hallucinates repos that don't exist. Stack Overflow answers are outdated.&lt;/p&gt;

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

&lt;p&gt;I built an AI-powered search engine that indexes 10,000+ repos from AWS's official GitHub organizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;aws-samples&lt;/strong&gt;: 8,031 repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;awslabs&lt;/strong&gt;: 993 repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-solutions-library-samples&lt;/strong&gt;: 315 repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-ia&lt;/strong&gt;: 234 repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aws-solutions&lt;/strong&gt;: 72 repos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The search uses a hybrid approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;70% BM25&lt;/strong&gt; (keyword matching) — catches exact AWS service names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;30% FAISS&lt;/strong&gt; (semantic vector search) — understands what you mean, not just what you type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each repo is classified by Amazon Bedrock (Nova Pro) across &lt;strong&gt;22 metadata fields&lt;/strong&gt;: solution type, AWS services used, complexity, freshness, setup time estimate, and more.&lt;/p&gt;

&lt;p&gt;Auto-indexed twice daily via EventBridge — new AWS repos are searchable within 12 hours.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Amazon Bedrock (Nova Pro) for AI classification&lt;/li&gt;
&lt;li&gt;FAISS with Titan Embed v2 (1024-dim) for vector search&lt;/li&gt;
&lt;li&gt;AWS Lambda (Docker, Python 3.12)&lt;/li&gt;
&lt;li&gt;API Gateway&lt;/li&gt;
&lt;li&gt;DynamoDB for usage tracking&lt;/li&gt;
&lt;li&gt;CloudFront + S3 for frontend&lt;/li&gt;
&lt;li&gt;EventBridge for scheduled indexing&lt;/li&gt;
&lt;li&gt;AWS CDK (TypeScript) for infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Architecture Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why hybrid search over pure vector?&lt;/strong&gt;&lt;br&gt;
AWS service names are precise — "Lambda" means something specific. Pure semantic search sometimes returns "serverless compute" results when you specifically want Lambda. BM25 catches exact matches, FAISS catches intent. The 70/30 split was tuned through testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why FAISS over OpenSearch?&lt;/strong&gt;&lt;br&gt;
Cost. OpenSearch Serverless has a minimum cost that runs 24/7. FAISS on Lambda + S3 costs under $6/month for the search component. For a bootstrapped product, that matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why 22 metadata fields?&lt;/strong&gt;&lt;br&gt;
Developers don't just want to find a repo — they want to know: Is it maintained? How complex is it? What AWS services does it use? How long will setup take? Nova Pro classifies each repo across all 22 fields automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hybrid search beats pure vector for domain-specific queries&lt;/li&gt;
&lt;li&gt;FAISS on Lambda is surprisingly cost-effective&lt;/li&gt;
&lt;li&gt;The 22-field classification is what makes results actually useful — not just the search itself&lt;/li&gt;
&lt;li&gt;Auto-indexing twice daily keeps results fresh without manual work&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Free to use — 3 searches without registration, 10 per day with a free account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://awssolutionfinder.solutions.cloudnestle.com/search?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=launch" rel="noopener noreferrer"&gt;AWS Solution Finder&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Exploring ways to improve relevance scoring and add more metadata fields. If you've worked with FAISS or hybrid search, I'd love to hear your approach.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built solo by an AWS Community Builder. Questions? Drop a comment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>devtools</category>
      <category>serverless</category>
    </item>
    <item>
      <title># Building a Mobile AI Assistant with Kiro CLI and the Agent Client Protocol</title>
      <dc:creator>Ajit</dc:creator>
      <pubDate>Tue, 24 Mar 2026 11:14:41 +0000</pubDate>
      <link>https://dev.to/aws-builders/-building-a-mobile-ai-assistant-with-kiro-cli-and-the-agent-client-protocol-258d</link>
      <guid>https://dev.to/aws-builders/-building-a-mobile-ai-assistant-with-kiro-cli-and-the-agent-client-protocol-258d</guid>
      <description>&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/mxfAifdPCJE"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  Situation
&lt;/h2&gt;

&lt;p&gt;AI coding assistants are powerful — but they're trapped. Locked inside your terminal or IDE. Step away from your desk and you lose access to your AI agent, your workspace context, your tools.&lt;/p&gt;

&lt;p&gt;I work across multiple environments — laptop, phone, sometimes just a quick check between meetings. My AI assistant (Kiro CLI) knows my codebase, has access to MCP tools (web search, AWS docs), and can read/write files. But only when I'm sitting at my terminal.&lt;/p&gt;

&lt;p&gt;The question: &lt;strong&gt;Can I take my AI agent mobile without rebuilding it from scratch?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task
&lt;/h2&gt;

&lt;p&gt;Build a bridge that connects Kiro CLI to Telegram — so I can message my AI assistant from my phone and get the same capabilities as the terminal: file access, tool execution, MCP servers, streamed responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraints:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No modifications to Kiro CLI itself — use its public protocol&lt;/li&gt;
&lt;li&gt;Channel-agnostic architecture — Telegram today, Slack/Discord tomorrow&lt;/li&gt;
&lt;li&gt;Real tool access — not just a chatbot wrapper, but actual file reads, terminal commands, web search&lt;/li&gt;
&lt;li&gt;Production-ready — auth, error handling, message splitting, typing indicators&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Action
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Discovering ACP
&lt;/h3&gt;

&lt;p&gt;Kiro CLI implements the &lt;a href="https://agentclientprotocol.com" rel="noopener noreferrer"&gt;Agent Client Protocol (ACP)&lt;/a&gt; — an open standard for AI agent communication, similar to how LSP standardized language servers. It uses JSON-RPC 2.0 over stdio.&lt;/p&gt;

&lt;p&gt;This means any process that can spawn &lt;code&gt;kiro-cli acp&lt;/code&gt; and pipe JSON through stdin/stdout becomes an ACP client. Not just IDEs — anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&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%2F8tivhhu73df8hekoyr40.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%2F8tivhhu73df8hekoyr40.png" alt="Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three layers, cleanly separated using the &lt;strong&gt;Adapter Pattern&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Telegram Adapter&lt;/strong&gt; — Auth, typing indicators, message splitting. Knows nothing about ACP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACP Client&lt;/strong&gt; — JSON-RPC transport. Manages protocol lifecycle. Knows nothing about Telegram.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kiro CLI&lt;/strong&gt; — AI agent runtime. Model inference, tool execution, MCP servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Swap Telegram for Slack by writing a new adapter. The ACP client stays identical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the ACP Handshake
&lt;/h3&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%2Fkiey53wvzvbb1pj8x30r.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%2Fkiey53wvzvbb1pj8x30r.png" alt="Protocol Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ACP has a clear lifecycle — initialize, create session, prompt, stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Step 1: Spawn Kiro CLI as ACP agent&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kiro-cli&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;acp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--trust-all-tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/path/to/workspace&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Step 2: Initialize — exchange capabilities&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initialize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;protocolVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientCapabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;readTextFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;writeTextFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;terminal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;clientInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Step 3: Create session&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session/new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/path/to/workspace&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mcpServers&lt;/span&gt;&lt;span class="p"&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;The &lt;code&gt;clientCapabilities&lt;/code&gt; declaration is the key insight — it tells Kiro what your client can handle. Declare &lt;code&gt;fs.readTextFile: true&lt;/code&gt; and Kiro will send file read requests to your client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Kiro sends requests TO us when it needs tools&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleServerRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs/readTextFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;terminal/execute&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&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;h3&gt;
  
  
  Streaming Responses
&lt;/h3&gt;

&lt;p&gt;ACP streams responses via &lt;code&gt;session/update&lt;/code&gt; notifications — each containing a text chunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;sessionUpdate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent_message_chunk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;session/prompt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&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;h3&gt;
  
  
  Adding MCP Tools
&lt;/h3&gt;

&lt;p&gt;MCP servers extend the agent with external capabilities. One JSON config gives the bot web search:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tools"&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="s2"&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;"mcpServers"&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;"web-search"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo-mcp-server"&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;Ask the bot "What's the weather in Tokyo?" — Kiro automatically invokes the search tool, processes results, and responds. All within a single &lt;code&gt;session/prompt&lt;/code&gt; call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wiring Telegram
&lt;/h3&gt;

&lt;p&gt;The adapter is the simplest layer — receive, forward, respond:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allowedUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendChatAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;splitMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&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;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;~200 lines of code.&lt;/strong&gt; A fully functional mobile AI assistant that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Connects to Kiro CLI via ACP (JSON-RPC 2.0 over stdio)&lt;/li&gt;
&lt;li&gt;✅ Full workspace access — reads files, writes files, runs terminal commands&lt;/li&gt;
&lt;li&gt;✅ MCP tool integration — web search, AWS docs, custom tools&lt;/li&gt;
&lt;li&gt;✅ Streamed responses — no waiting for the full response to generate&lt;/li&gt;
&lt;li&gt;✅ Auth, typing indicators, automatic message splitting for Telegram's 4096 char limit&lt;/li&gt;
&lt;li&gt;✅ Channel-agnostic — adding Slack or Discord means writing one new adapter file&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Patterns That Made It Work
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adapter Pattern&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Telegram adapter is decoupled from ACP. New channels = new adapter, same core.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JSON-RPC 2.0 / stdio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same transport as LSP. Battle-tested, no HTTP overhead, works with any language.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capability Negotiation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client declares what it supports during &lt;code&gt;initialize&lt;/code&gt;. Forward-compatible.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bidirectional Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client sends prompts, agent sends tool requests back. Both sides are client and server.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streaming via Notifications&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agent streams chunks as generated. No polling, no buffering.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Key Learnings
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACP is underutilized.&lt;/strong&gt; Most people use Kiro in the terminal or IDE. But ACP is a general-purpose protocol — any client that speaks JSON-RPC can connect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MCP servers are the real power.&lt;/strong&gt; The bot isn't just a chatbot — it's an agent with tools. Web search, AWS docs, file operations. MCP turns text generation into action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;stdio is elegant.&lt;/strong&gt; No HTTP servers, no WebSocket complexity, no ports. Spawn a process, pipe JSON, done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Adapter Pattern pays off immediately.&lt;/strong&gt; Started with Telegram. Slack would take an afternoon because the ACP client is completely separate.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Multi-channel&lt;/strong&gt; — Slack and WhatsApp adapters using the same ACP client&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Voice messages&lt;/strong&gt; — Speech-to-text → prompt → response → voice note&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Serverless&lt;/strong&gt; — Lambda + API Gateway with Telegram webhooks&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Session persistence&lt;/strong&gt; — Resume conversations across restarts&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The full source is open: &lt;strong&gt;&lt;a href="https://github.com/ajitnk-lab/kiro-acp-telegram-bot" rel="noopener noreferrer"&gt;kiro-acp-telegram-bot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MIT-0 licensed. Fork it, extend it, build your own channels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ajitnk-lab/kiro-acp-telegram-bot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;kiro-acp-telegram-bot
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env  &lt;span class="c"&gt;# add your Telegram token&lt;/span&gt;
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;I'd love your feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What channels would you connect next?&lt;/li&gt;
&lt;li&gt;Would a serverless (Lambda) deployment be useful?&lt;/li&gt;
&lt;li&gt;What MCP servers would you want on your phone?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment or open an issue on the repo. If you build something with this — a Slack bot, a Discord integration, a voice assistant — let me know. 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with &lt;a href="https://kiro.dev/cli/" rel="noopener noreferrer"&gt;Kiro CLI&lt;/a&gt; · &lt;a href="https://agentclientprotocol.com" rel="noopener noreferrer"&gt;Agent Client Protocol&lt;/a&gt; · &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/docs/cli/" rel="noopener noreferrer"&gt;Kiro CLI Documentation&lt;/a&gt; — Installation, authentication, usage&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/docs/cli/acp/" rel="noopener noreferrer"&gt;Kiro ACP Integration Guide&lt;/a&gt; — Supported methods, session updates, Kiro extensions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://agentclientprotocol.com" rel="noopener noreferrer"&gt;Agent Client Protocol Specification&lt;/a&gt; — The open standard for AI agent-editor communication&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/docs/cli/mcp/" rel="noopener noreferrer"&gt;Kiro MCP Configuration&lt;/a&gt; — Setting up MCP servers (stdio + HTTP)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/docs/cli/custom-agents/" rel="noopener noreferrer"&gt;Kiro Custom Agents&lt;/a&gt; — Agent JSON config, hooks, MCP server selection&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; — Anthropic's open standard for AI tool integration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.jsonrpc.org/specification" rel="noopener noreferrer"&gt;JSON-RPC 2.0 Specification&lt;/a&gt; — The transport protocol ACP is built on&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://core.telegram.org/bots/api" rel="noopener noreferrer"&gt;Telegram Bot API&lt;/a&gt; — Bot creation, message handling, polling vs webhooks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/changelog/cli/1-25/" rel="noopener noreferrer"&gt;ACP Changelog — Kiro 1.25&lt;/a&gt; — ACP launch, MCP tools, session management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/devops/exploring-the-latest-features-of-the-amazon-q-developer-cli/" rel="noopener noreferrer"&gt;Exploring the latest features of Amazon Q Developer CLI&lt;/a&gt; — Background on CLI + MCP architecture&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>devtools</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
