<?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: Pulkit Verma</title>
    <description>The latest articles on DEV Community by Pulkit Verma (@pulkit_verma_9e34a3ceb001).</description>
    <link>https://dev.to/pulkit_verma_9e34a3ceb001</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4135930%2Fe5f4a607-da64-4dc7-8415-b572949a7def.jpg</url>
      <title>DEV Community: Pulkit Verma</title>
      <link>https://dev.to/pulkit_verma_9e34a3ceb001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pulkit_verma_9e34a3ceb001"/>
    <language>en</language>
    <item>
      <title>working code</title>
      <dc:creator>Pulkit Verma</dc:creator>
      <pubDate>Mon, 21 Sep 2026 14:43:54 +0000</pubDate>
      <link>https://dev.to/pulkit_verma_9e34a3ceb001/working-code-7c1</link>
      <guid>https://dev.to/pulkit_verma_9e34a3ceb001/working-code-7c1</guid>
      <description>&lt;p&gt;use this code in cmd&lt;br&gt;
pip install httpx pydantic openai&lt;/p&gt;

&lt;p&gt;this is python code&lt;br&gt;
import asyncio&lt;br&gt;
import json&lt;br&gt;
from typing import Any, Dict, List, Optional&lt;br&gt;
import httpx&lt;br&gt;
from openai import AsyncOpenAI&lt;br&gt;
from pydantic import BaseModel, Field, ValidationError&lt;/p&gt;

&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;h1&gt;
  
  
  1. Typed Schemas (Input &amp;amp; Output Boundary Contracts)
&lt;/h1&gt;

&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;p&gt;class SearchParams(BaseModel):&lt;br&gt;
    """Defensive schema defining what parameters the LLM is permitted to send."""&lt;br&gt;
    query: str = Field(..., description="Target search query optimized for document lookup")&lt;br&gt;
    top_k: int = Field(default=3, ge=1, le=5, description="Number of results (clamped between 1 and 5)")&lt;br&gt;
    category: Optional[str] = Field(default=None, description="Optional category filter")&lt;/p&gt;

&lt;p&gt;class ContentChunk(BaseModel):&lt;br&gt;
    """Standardized ingested payload structure."""&lt;br&gt;
    id: str&lt;br&gt;
    source_url: str&lt;br&gt;
    text: str&lt;br&gt;
    score: float&lt;/p&gt;

&lt;p&gt;class GroundedAgentResponse(BaseModel):&lt;br&gt;
    """Final answer format forcing the LLM to provide verifiable citations."""&lt;br&gt;
    answer: str = Field(..., description="The direct answer synthesized from context")&lt;br&gt;
    cited_chunk_ids: List[str] = Field(&lt;br&gt;
        default_factory=list, &lt;br&gt;
        description="The exact chunk IDs used as evidence for this answer"&lt;br&gt;
    )&lt;/p&gt;

&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;h1&gt;
  
  
  2. Defensive Network Tool
&lt;/h1&gt;

&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;p&gt;async def fetch_live_content(params: SearchParams) -&amp;gt; List[ContentChunk]:&lt;br&gt;
    """&lt;br&gt;
    Executes a network fetch guarded by strict timeouts, exception handling,&lt;br&gt;
    and structured schema validation.&lt;br&gt;
    """&lt;br&gt;
    timeout = httpx.Timeout(4.0, connect=2.0)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In production, point this to your actual internal API or hybrid search endpoint
url = "https://jsonplaceholder.typicode.com/posts"

async with httpx.AsyncClient(timeout=timeout) as client:
    try:
        response = await client.get(url, params={"_limit": params.top_k})
        response.raise_for_status()
        raw_data = response.json()

        # Transform and validate external payload into typed ContentChunks
        chunks: List[ContentChunk] = []
        for item in raw_data:
            chunk = ContentChunk(
                id=f"doc-{item.get('id')}",
                source_url=f"https://example.com/posts/{item.get('id')}",
                text=f"{item.get('title')}: {item.get('body')}".replace("\n", " "),
                score=1.0,
            )
            chunks.append(chunk)
        return chunks

    except (httpx.TimeoutException, httpx.HTTPStatusError, httpx.RequestError) as err:
        # Defensive logging; fall back gracefully so the agent doesn't crash
        print(f"[Tool Warning] External fetch failed: {err}. Falling back to empty set.")
        return []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;
&lt;h1&gt;
  
  
  3. Agent Execution Engine
&lt;/h1&gt;
&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;p&gt;class ProductionAgent:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self, model_name: str = "gpt-4o-mini"):&lt;br&gt;
        self.client = AsyncOpenAI()&lt;br&gt;
        self.model_name = model_name&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Tool mapping for deterministic runtime execution
    self.tools_map = {
        "fetch_live_content": fetch_live_content
    }

    # OpenAI Tool Schema declaration derived directly from Pydantic
    self.tool_definitions = [
        {
            "type": "function",
            "function": {
                "name": "fetch_live_content",
                "description": "Fetch live verified articles and real-time knowledge.",
                "parameters": SearchParams.model_json_schema()
            }
        }
    ]

async def run(self, user_query: str) -&amp;gt; GroundedAgentResponse:
    messages = [
        {
            "role": "system",
            "content": (
                "You are a production assistant answering queries using live content. "
                "Always call `fetch_live_content` to retrieve information before answering. "
                "Ground your answers strictly on the retrieved chunks and cite their IDs."
            )
        },
        {"role": "user", "content": user_query}
    ]

    # Step 1: Initial invocation (Model decides whether to call a tool)
    first_response = await self.client.chat.completions.create(
        model=self.model_name,
        messages=messages,
        tools=self.tool_definitions,
        tool_choice="auto"
    )

    response_message = first_response.choices[0].message
    messages.append(response_message)

    retrieved_chunk_ids = set()

    # Step 2: Handle Tool Calls defensively
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            func_name = tool_call.function.name
            func_args_str = tool_call.function.arguments

            if func_name == "fetch_live_content":
                try:
                    # Defensive validation: parse arguments through Pydantic
                    raw_args = json.loads(func_args_str)
                    validated_params = SearchParams(**raw_args)

                    # Execute asynchronous fetch
                    chunks = await self.tools_map&amp;lt;a href="validated_params"&amp;gt;func_name&amp;lt;/a&amp;gt;
                    retrieved_chunk_ids.update(c.id for c in chunks)

                    # Serialize chunks for the LLM
                    tool_result_content = json.dumps([c.model_dump() for c in chunks])
                except (ValidationError, json.JSONDecodeError) as e:
                    tool_result_content = json.dumps({"error": f"Invalid tool arguments: {str(e)}"})

                # Append execution output back into context
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "name": func_name,
                    "content": tool_result_content
                })

    # Step 3: Final Synthesis with Structured Output
    final_completion = await self.client.beta.chat.completions.parse(
        model=self.model_name,
        messages=messages,
        response_format=GroundedAgentResponse
    )

    final_answer: GroundedAgentResponse = final_completion.choices[0].message.parsed

    # Step 4: Deterministic Grounding Verification
    self._verify_citations(final_answer, retrieved_chunk_ids)

    return final_answer

@staticmethod
def _verify_citations(response: GroundedAgentResponse, valid_ids: set) -&amp;gt; None:
    """
    Hardening step: ensures the agent did not invent non-existent citation IDs.
    """
    hallucinated_ids = [cid for cid in response.cited_chunk_ids if cid not in valid_ids]
    if hallucinated_ids:
        print(f"[Verification Alert] Hallucinated citation IDs detected: {hallucinated_ids}")
        # Prune out hallucinated IDs to ensure client-side trust
        response.cited_chunk_ids = [cid for cid in response.cited_chunk_ids if cid in valid_ids]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;
&lt;h1&gt;
  
  
  4. Entrypoint
&lt;/h1&gt;
&lt;h1&gt;
  
  
  =====================================================================
&lt;/h1&gt;

&lt;p&gt;async def main():&lt;br&gt;
    agent = ProductionAgent()&lt;br&gt;
    user_prompt = "What are the latest updates about project announcement posts?"&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(f"User: {user_prompt}\nRunning agent...")
result = await agent.run(user_prompt)

print("\n--- Final Grounded Output ---")
print(f"Answer:\n{result.answer}\n")
print(f"Verified Source IDs: {result.cited_chunk_ids}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    asyncio.run(main())&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
    <item>
      <title>Defensive Agent Architecture</title>
      <dc:creator>Pulkit Verma</dc:creator>
      <pubDate>Mon, 21 Sep 2026 14:36:41 +0000</pubDate>
      <link>https://dev.to/pulkit_verma_9e34a3ceb001/defensive-agent-architecture-25g</link>
      <guid>https://dev.to/pulkit_verma_9e34a3ceb001/defensive-agent-architecture-25g</guid>
      <description>&lt;p&gt;Schema Injection: SearchParams.model_json_schema() is passed into the LLM's tool/function calling definition.&lt;/p&gt;

&lt;p&gt;Deterministic Invocation: The LLM outputs a JSON payload matching SearchParams.&lt;/p&gt;

&lt;p&gt;Execution &amp;amp; Validation: fetch_live_content validates the arguments, dispatches the HTTP call within a strict 4-second window, and deserializes the results into ContentChunk objects.&lt;/p&gt;

&lt;p&gt;Context Injection: The serialized chunks and their respective ids are injected back into the LLM context for synthesis and citation grounding.&lt;/p&gt;

&lt;p&gt;This pattern addresses a critical failure mode in AI engineering: the fragility of connecting probabilistic language models to deterministic production systems.&lt;/p&gt;

&lt;p&gt;The Problems It Solves&lt;br&gt;
Hallucinated Tool Inputs: LLMs frequently drift or generate malformed parameters (e.g., requesting -10 or 1,000,000 items, or passing unparseable types). Defining the input via SearchParams forces the model to conform to strict boundaries (ge=1, le=10), catching invalid tool requests before they hit your infrastructure.&lt;/p&gt;

&lt;p&gt;Agent Hanging and Runaway Costs: Without rigid timeouts, a lagging external API or vector index will cause the agent to hang indefinitely. This blocks server threads, degrades user experience, and inflates cloud costs. The explicit 4-second timeout enforces a deterministic upper bound on wait times.&lt;/p&gt;

&lt;p&gt;Cascading Application Crashes: Unhandled HTTP errors (429 rate limits, 500 server crashes) crash naive agent runtimes. Swallowing these failures into a structured fallback (return []) allows the agent to handle missing data gracefully rather than throwing an uncaught exception.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
