<?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: Sanjeev Kumar</title>
    <description>The latest articles on DEV Community by Sanjeev Kumar (@sanjeev_kumar_1755fc90023).</description>
    <link>https://dev.to/sanjeev_kumar_1755fc90023</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%2F3799448%2F7ff4e848-a503-4381-a46a-713a467d09e3.png</url>
      <title>DEV Community: Sanjeev Kumar</title>
      <link>https://dev.to/sanjeev_kumar_1755fc90023</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanjeev_kumar_1755fc90023"/>
    <language>en</language>
    <item>
      <title>How We Made Grantex Enterprise-Grade: 3,332 Tests, Zero Failures</title>
      <dc:creator>Sanjeev Kumar</dc:creator>
      <pubDate>Sun, 05 Apr 2026 12:34:49 +0000</pubDate>
      <link>https://dev.to/sanjeev_kumar_1755fc90023/how-we-made-grantex-enterprise-grade-3332-tests-zero-failures-4knp</link>
      <guid>https://dev.to/sanjeev_kumar_1755fc90023/how-we-made-grantex-enterprise-grade-3332-tests-zero-failures-4knp</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; We ran a comprehensive security, resilience, and API quality audit on Grantex — the open authorization protocol for AI agents. We found and fixed 20+ issues across security (timing attacks, missing rate limits, open CORS), resilience (no DB transactions, no connection pools, no retry logic), and API consistency (phantom types, inconsistent error codes). The result: 3,332 tests across 27 packages with a 100% pass rate.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Grantex?
&lt;/h2&gt;

&lt;p&gt;Grantex is OAuth 2.0 for AI agents. When an AI agent calls Salesforce, Jira, or Stripe on behalf of a human, Grantex ensures the agent can only do what it was authorized to do — read contacts, not delete them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 SDKs: TypeScript, Python, Go&lt;/li&gt;
&lt;li&gt;53 pre-built tool manifests for scope enforcement&lt;/li&gt;
&lt;li&gt;Integrations: LangChain, Anthropic, OpenAI Agents, CrewAI, Google ADK, Vercel AI, MCP&lt;/li&gt;
&lt;li&gt;W3C Verifiable Credentials, FIDO2/WebAuthn, DID infrastructure&lt;/li&gt;
&lt;li&gt;Apache 2.0, IETF Internet-Draft&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Audit
&lt;/h2&gt;

&lt;p&gt;We ran 5 parallel deep-dive audits:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Security Audit
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;Admin authentication using &lt;code&gt;!==&lt;/code&gt; (timing-attack vulnerable)&lt;/li&gt;
&lt;li&gt;Zero rate limits on signup, session creation, SAML callbacks&lt;/li&gt;
&lt;li&gt;CORS wide open (default Fastify config)&lt;/li&gt;
&lt;li&gt;SSO state parameter was plain base64 (forgeable)&lt;/li&gt;
&lt;li&gt;JWT &lt;code&gt;exp&lt;/code&gt; claim not validated in grant introspection&lt;/li&gt;
&lt;li&gt;No scope format validation (could send 10MB scope strings)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;crypto.timingSafeEqual()&lt;/code&gt; for admin auth&lt;/li&gt;
&lt;li&gt;Rate limits on every POST/PATCH/DELETE endpoint&lt;/li&gt;
&lt;li&gt;CORS locked to &lt;code&gt;origin: false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SSO state HMAC-signed with timing-safe verification&lt;/li&gt;
&lt;li&gt;JWT expiry validated&lt;/li&gt;
&lt;li&gt;Scope validation: max 256 chars, max 100 scopes&lt;/li&gt;
&lt;li&gt;7 HTTP security headers (HSTS, X-Content-Type-Options, X-Frame-Options, etc.)&lt;/li&gt;
&lt;li&gt;1MB body size limit&lt;/li&gt;
&lt;li&gt;Input trimming on all string fields&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Resilience Audit
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;No database connection pool settings&lt;/li&gt;
&lt;li&gt;Token exchange: 4 sequential DB writes without transaction&lt;/li&gt;
&lt;li&gt;Redis errors silently swallowed&lt;/li&gt;
&lt;li&gt;No graceful shutdown (workers leaked on SIGTERM)&lt;/li&gt;
&lt;li&gt;Health check just returned 200 (didn't check DB or Redis)&lt;/li&gt;
&lt;li&gt;No SDK retry logic in any language&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Connection pools (max 20, idle 30s, connect 10s, lifetime 30min)&lt;/li&gt;
&lt;li&gt;Token exchange wrapped in &lt;code&gt;sql.begin()&lt;/code&gt; transaction&lt;/li&gt;
&lt;li&gt;Redis error handlers with reconnection logging&lt;/li&gt;
&lt;li&gt;Graceful shutdown: SIGTERM → stop workers → close Redis → close DB&lt;/li&gt;
&lt;li&gt;Deep health check: &lt;code&gt;SELECT 1&lt;/code&gt; + &lt;code&gt;PING&lt;/code&gt; with 2s timeout, 503 on degraded&lt;/li&gt;
&lt;li&gt;Config validation on startup (exits on missing DATABASE_URL, REDIS_URL, etc.)&lt;/li&gt;
&lt;li&gt;SDK retry with exponential backoff + jitter in TypeScript, Python, and Go&lt;/li&gt;
&lt;li&gt;Webhook retry jitter (20% randomization to prevent thundering herd)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. API Consistency Audit
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;SDK types defined pagination fields (total, page, pageSize) that the API never returned&lt;/li&gt;
&lt;li&gt;Admin error responses missing &lt;code&gt;code&lt;/code&gt; and &lt;code&gt;requestId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;HTTP 422 used for parse errors (should be 400)&lt;/li&gt;
&lt;li&gt;Inconsistent error formats across routes&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;SDK types aligned with actual API responses&lt;/li&gt;
&lt;li&gt;All error responses standardized: &lt;code&gt;{ message, code, requestId }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;422 reserved for semantic validation only&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Observability
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;console.log&lt;/code&gt; and &lt;code&gt;console.error&lt;/code&gt; everywhere&lt;/li&gt;
&lt;li&gt;No structured logging&lt;/li&gt;
&lt;li&gt;No log levels&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Structured pino JSON logging (zero &lt;code&gt;console.*&lt;/code&gt; remaining)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LOG_LEVEL&lt;/code&gt; env var with dev-mode &lt;code&gt;pino-pretty&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Worker child loggers with context bindings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Documentation Gaps
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;29 API endpoints implemented but undocumented&lt;/li&gt;
&lt;li&gt;SDK overview tables missing 6-9 resource clients&lt;/li&gt;
&lt;li&gt;4 SDK docs pages missing (Python/Go vault + passports)&lt;/li&gt;
&lt;li&gt;No Security Hardening guide&lt;/li&gt;
&lt;li&gt;No Operations guide&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;35 new API reference pages&lt;/li&gt;
&lt;li&gt;All overview tables complete (20/20 services)&lt;/li&gt;
&lt;li&gt;Security Hardening + Operations guides&lt;/li&gt;
&lt;li&gt;SDK retry configuration documented&lt;/li&gt;
&lt;li&gt;CHANGELOG updated&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security issues&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Endpoints with rate limits&lt;/td&gt;
&lt;td&gt;~5&lt;/td&gt;
&lt;td&gt;All&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK retry logic&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;All 3 languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Health check depth&lt;/td&gt;
&lt;td&gt;Shallow (200 always)&lt;/td&gt;
&lt;td&gt;DB + Redis (503 on degraded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structured logging&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Full pino&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test count&lt;/td&gt;
&lt;td&gt;~2,800&lt;/td&gt;
&lt;td&gt;3,332&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass rate&lt;/td&gt;
&lt;td&gt;~99%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packages tested&lt;/td&gt;
&lt;td&gt;~20&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/sdk    &lt;span class="c"&gt;# TypeScript&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex          &lt;span class="c"&gt;# Python&lt;/span&gt;
go get github.com/mishrasanjeev/grantex-go  &lt;span class="c"&gt;# Go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mishrasanjeev/grantex" rel="noopener noreferrer"&gt;https://github.com/mishrasanjeev/grantex&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.grantex.dev" rel="noopener noreferrer"&gt;https://docs.grantex.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discord:&lt;/strong&gt; &lt;a href="https://discord.gg/QuSk7AeBdg" rel="noopener noreferrer"&gt;https://discord.gg/QuSk7AeBdg&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security guide:&lt;/strong&gt; &lt;a href="https://docs.grantex.dev/guides/security-hardening" rel="noopener noreferrer"&gt;https://docs.grantex.dev/guides/security-hardening&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operations guide:&lt;/strong&gt; &lt;a href="https://docs.grantex.dev/guides/operations" rel="noopener noreferrer"&gt;https://docs.grantex.dev/guides/operations&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Star the repo if you're building AI agents that need real authorization.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Grantex is Apache 2.0 licensed. IETF Internet-Draft submitted. SOC 2 Type I certified.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>security</category>
      <category>testing</category>
    </item>
    <item>
      <title>Why AI Agents Need Their Own Authorization Protocol (and How We Built One)</title>
      <dc:creator>Sanjeev Kumar</dc:creator>
      <pubDate>Sun, 15 Mar 2026 12:17:52 +0000</pubDate>
      <link>https://dev.to/sanjeev_kumar_1755fc90023/why-ai-agents-need-their-own-authorization-protocol-and-how-we-built-one-23oo</link>
      <guid>https://dev.to/sanjeev_kumar_1755fc90023/why-ai-agents-need-their-own-authorization-protocol-and-how-we-built-one-23oo</guid>
      <description>&lt;p&gt;Every AI agent framework — LangChain, CrewAI, OpenAI Agents SDK, Vercel AI — has the same blind spot: authorization.&lt;/p&gt;

&lt;p&gt;Your agent can read emails, book meetings, deploy infrastructure, and spend money. But how does it prove it's allowed to? The answer, for most teams,&lt;br&gt;&lt;br&gt;
  is an API key with full access stuffed into an environment variable.&lt;/p&gt;

&lt;p&gt;That's not authorization. That's a breach waiting to happen.&lt;/p&gt;

&lt;p&gt;## The problem with API keys for agents&lt;/p&gt;

&lt;p&gt;API keys were designed for server-to-server auth. They assume a single trusted caller. AI agents break every one of those assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No scoping.&lt;/strong&gt; The agent has the same permissions as the key owner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No consent.&lt;/strong&gt; The user never approved what the agent can do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No per-agent identity.&lt;/strong&gt; You know the key was used, but not which agent used it, or why.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No revocation granularity.&lt;/strong&gt; One agent misbehaves? Rotate the key. That kills every agent sharing it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No delegation control.&lt;/strong&gt; Agent A calls Agent B? You're copy-pasting credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No spending limits.&lt;/strong&gt; An agent with a cloud API key can provision unlimited resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OAuth 2.0 solved this for web apps 15 years ago. IAM solved it for cloud infrastructure. AI agents have nothing.&lt;/p&gt;

&lt;p&gt;## Grantex: delegated authorization for agents&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mishrasanjeev/grantex" rel="noopener noreferrer"&gt;Grantex&lt;/a&gt; is an open protocol (Apache 2.0) that gives AI agents scoped, time-limited, revocable permissions —&lt;br&gt;
   with user consent.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your app requests authorization&lt;/strong&gt; for a specific agent and specific scopes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The user consents&lt;/strong&gt; (optionally with FIDO2/WebAuthn passkey)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent receives a signed JWT&lt;/strong&gt; with scoped claims — &lt;code&gt;calendar:read&lt;/code&gt;, &lt;code&gt;email:send&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any service verifies the token offline&lt;/strong&gt; via JWKS — no callback to an auth server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tokens expire, can be revoked, and are fully audited&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
typescript
  import { Grantex } from '@grantex/sdk';

  const gx = new Grantex({ apiKey });

  // Request authorization
  const auth = await gx.authorize({
    agentId: 'agent-123',
    userId: 'user-456',
    scopes: ['calendar:read', 'email:send'],
  });

  // Exchange for a grant token
  const { grantToken } = await gx.tokens.exchange({
    code: auth.code,
    agentId: 'agent-123',
  });

  // Verify anywhere — offline
  const grant = await verifyGrantToken(grantToken, {
    jwksUri: 'https://your-server/.well-known/jwks.json',
  });
  // grant.scopes → ['calendar:read', 'email:send']

  Works the same in Python:

  from grantex import Grantex

  gx = Grantex(api_key="...")
  auth = gx.authorize(agent_id="agent-123", user_id="user-456", scopes=["calendar:read"])
  result = gx.tokens.exchange(code=auth.code, agent_id="agent-123")

  And Go:

  client := grantex.New("your-api-key")
  auth, _ := client.Authorize(ctx, grantex.AuthorizeParams{
      AgentID: "agent-123",
      UserID:  "user-456",
      Scopes:  []string{"calendar:read"},
  })

  Delegation: agents authorizing other agents

  This is where it gets interesting. In real agentic systems, agents call other agents. A travel planner agent delegates to a booking agent, which       
  delegates to a payment agent.

  Grantex supports delegation chains with scope narrowing and depth limits:

  const delegation = await gx.grants.delegate({
    parentGrantToken: travelPlannerToken,
    subAgentId: 'booking-agent',
    scopes: ['booking:create'], // narrower than parent
  });

  Revoke the parent? Every child delegation dies automatically. Cascade revocation.

  Budget controls

  Give an agent a spending limit. The protocol enforces it atomically — no race conditions:

  await gx.budgets.allocate({
    grantId,
    amount: 50.00,
    currency: 'USD',
  });

  // Agent tries to spend
  const result = await gx.budgets.debit({
    grantId,
    amount: 12.50,
  });
  // result.remaining → 37.50

  Exceed the budget? The agent gets a 402 INSUFFICIENT_BUDGET. Not a silent failure — a hard stop.

  What else is in the box

  - FIDO2/WebAuthn — passkeys for consent approval
  - W3C Verifiable Credentials — portable agent identity
  - SD-JWT — selective disclosure (agent proves specific claims without revealing everything)
  - Real-time events — SSE/WebSocket streams for authorization events
  - Full audit trail — every action logged and queryable

  Framework integrations

  Drop-in integrations for the frameworks you're already using:

  ┌─────────────────────┬───────────────────────┐
  │      Framework      │        Package        │
  ├─────────────────────┼───────────────────────┤
  │ LangChain           │ @grantex/langchain    │
  ├─────────────────────┼───────────────────────┤
  │ CrewAI              │ grantex-crewai        │
  ├─────────────────────┼───────────────────────┤
  │ OpenAI Agents SDK   │ grantex-openai-agents │
  ├─────────────────────┼───────────────────────┤
  │ Vercel AI           │ @grantex/vercel-ai    │
  ├─────────────────────┼───────────────────────┤
  │ Google ADK          │ grantex-adk           │
  ├─────────────────────┼───────────────────────┤
  │ AutoGen             │ @grantex/autogen      │
  ├─────────────────────┼───────────────────────┤
  │ Express.js          │ @grantex/express      │
  ├─────────────────────┼───────────────────────┤
  │ FastAPI             │ grantex-fastapi       │
  ├─────────────────────┼───────────────────────┤
  │ MCP (Claude/Cursor) │ @grantex/mcp          │
  ├─────────────────────┼───────────────────────┤
  │ Terraform           │ grantex provider      │
  └─────────────────────┴───────────────────────┘

  Standards track

  This isn't a weekend project. The protocol has:

  - An IETF Internet-Draft submitted to the OAuth Working Group
  - A NIST NCCoE public comment filed
  - AuthZEN conformance mapping
  - SOC 2 Type I certification completed
  - A frozen, public https://github.com/mishrasanjeev/grantex/blob/main/SPEC.md

  Try it

  Everything is open source under Apache 2.0:

  - GitHub: https://github.com/mishrasanjeev/grantex
  - Docs: https://docs.grantex.dev
  - Playground: https://grantex.dev/playground

  npm install @grantex/sdk    # TypeScript
  pip install grantex          # Python
  go get github.com/mishrasanjeev/grantex-go  # Go

  If you're building agents that act on behalf of users, I'd love to hear how you're handling authorization today — and what's broken about it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Add Authorization to Your AI Agent (LangChain, CrewAI, OpenAI Agents, and More)</title>
      <dc:creator>Sanjeev Kumar</dc:creator>
      <pubDate>Wed, 04 Mar 2026 14:58:01 +0000</pubDate>
      <link>https://dev.to/sanjeev_kumar_1755fc90023/how-to-add-authorization-to-your-ai-agent-langchain-crewai-openai-agents-and-more-90c</link>
      <guid>https://dev.to/sanjeev_kumar_1755fc90023/how-to-add-authorization-to-your-ai-agent-langchain-crewai-openai-agents-and-more-90c</guid>
      <description>&lt;h1&gt;
  
  
  How to Add Authorization to Your AI Agent (LangChain, CrewAI, OpenAI Agents, and More)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;: ai, security, python, typescript&lt;br&gt;
&lt;strong&gt;Series&lt;/strong&gt;: AI Agent Security&lt;br&gt;
&lt;strong&gt;Canonical URL&lt;/strong&gt;: &lt;a href="https://grantex.dev/for/langchain" rel="noopener noreferrer"&gt;https://grantex.dev/for/langchain&lt;/a&gt; (or leave blank)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;AI agents are booking flights, sending emails, and moving money. Most of them run on all-or-nothing API keys.&lt;/p&gt;

&lt;p&gt;This is where the web was before OAuth 2.0 — and it's exactly as dangerous as it sounds.&lt;/p&gt;

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

&lt;p&gt;When you connect an AI agent to a real service — Stripe, Gmail, Salesforce — you typically give it an API key with full access. The agent can do anything the key allows. There's no scoping ("read emails but don't send"), no audit trail ("what did the agent do?"), and no revocation ("stop this agent NOW").&lt;/p&gt;

&lt;p&gt;This was fine when agents were demos. It's not fine when they're in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Need
&lt;/h2&gt;

&lt;p&gt;The web solved this 15 years ago with OAuth 2.0: users grant scoped, revocable access to applications. But OAuth was designed for human users clicking consent buttons. Agents are different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents spawn sub-agents&lt;/strong&gt; — a travel agent delegates to a flight booker and a hotel booker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents operate autonomously&lt;/strong&gt; — there's no human in the loop for every API call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents chain actions&lt;/strong&gt; — one agent's output becomes another agent's input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need OAuth-level security with agent-native primitives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Grantex
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://grantex.dev" rel="noopener noreferrer"&gt;Grantex&lt;/a&gt; is an open authorization protocol (Apache 2.0) for AI agents. The core flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A human approves a &lt;strong&gt;scoped, time-limited grant&lt;/strong&gt; for an agent&lt;/li&gt;
&lt;li&gt;The agent receives a &lt;strong&gt;signed JWT&lt;/strong&gt; it presents to any service&lt;/li&gt;
&lt;li&gt;Services &lt;strong&gt;verify offline&lt;/strong&gt; via JWKS — no Grantex account needed&lt;/li&gt;
&lt;li&gt;Every action is logged in an &lt;strong&gt;append-only, hash-chained audit trail&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The human can &lt;strong&gt;revoke access instantly&lt;/strong&gt; — effective in &amp;lt; 1 second&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Adding Authorization to Your Agent
&lt;/h2&gt;

&lt;h3&gt;
  
  
  LangChain
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/langchain @grantex/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Grantex&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grantex/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GrantexToolkit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grantex/langchain&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;gx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Grantex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GRANTEX_API_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Register your agent&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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="s1"&gt;research-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scopes&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="s1"&gt;search:read&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="s1"&gt;docs:write&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;// 2. Create an authorization request&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agent&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="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scopes&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="s1"&gt;search:read&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="s1"&gt;docs:write&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;// User approves at auth.consentUrl&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Exchange the code for a JWT&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;grantToken&lt;/span&gt; &lt;span class="p"&gt;}&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agent&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Wrap your LangChain tools&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolkit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GrantexToolkit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;grantToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;searchTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;docsTool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Tools now verify scopes before executing&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createToolCallingAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolkit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this gives you:&lt;/strong&gt; Every tool call checks that the agent's JWT has the required scopes. If the agent tries to call a tool it doesn't have permission for, it gets a clear error — not a silent failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grantex.dev/for/langchain" rel="noopener noreferrer"&gt;Full LangChain guide →&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CrewAI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex-crewai grantex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Grantex&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex_crewai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GrantexCrewTools&lt;/span&gt;

&lt;span class="n"&gt;gx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Grantex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GRANTEX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Each crew member gets its own scoped token
&lt;/span&gt;&lt;span class="n"&gt;researcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrantexCrewTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;grant_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;researcher_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# "search:read" only
&lt;/span&gt;    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrantexCrewTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;grant_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;writer_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# "docs:write" only
&lt;/span&gt;    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;write_tool&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 researcher can search but not write. The writer can write but not search. Revoke any crew member without stopping the whole crew.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grantex.dev/for/crewai" rel="noopener noreferrer"&gt;Full CrewAI guide →&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI Agents SDK
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex-openai-agents grantex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex_openai_agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GrantexTools&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrantexTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;grant_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://grantex.dev/for/openai-agents" rel="noopener noreferrer"&gt;Full OpenAI Agents guide →&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Google ADK
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex-adk grantex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex_adk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GrantexADKTools&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrantexADKTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;grant_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;calendar_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://grantex.dev/for/google-adk" rel="noopener noreferrer"&gt;Full Google ADK guide →&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel AI SDK
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/vercel-ai @grantex/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createGrantexTools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grantex/vercel-ai&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;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createGrantexTools&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;grantToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;searchTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emailTool&lt;/span&gt; &lt;span class="p"&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;result&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;generateText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;tools&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Book the cheapest flight to NYC&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edge-compatible. Works with streaming. TypeScript-first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grantex.dev/for/vercel-ai" rel="noopener noreferrer"&gt;Full Vercel AI guide →&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Protecting Your API (Service Side)
&lt;/h2&gt;

&lt;p&gt;If you're building the API that agents call, you need to verify their tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Express.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;grantexMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requireScopes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grantex/express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;grantexMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;jwksUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-auth/.well-known/jwks.json&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/emails&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;requireScopes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email:read&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// agent DID&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['email:read']&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;emails&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;p&gt;Sub-millisecond overhead. JWKS cached locally. &lt;a href="https://grantex.dev/for/express" rel="noopener noreferrer"&gt;Express guide →&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  FastAPI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex-fastapi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex_fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GrantexAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GrantContext&lt;/span&gt;

&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrantexAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwks_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://your-auth/.well-known/jwks.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/emails&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;grant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GrantContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require_scopes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email:read&lt;/span&gt;&lt;span class="sh"&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;emails&lt;/span&gt;&lt;span class="sh"&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;Async-native. Pydantic models. OpenAPI integration. &lt;a href="https://grantex.dev/for/fastapi" rel="noopener noreferrer"&gt;FastAPI guide →&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Scoping: What Else You Get
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Delegation chains&lt;/strong&gt; — A travel agent can delegate narrower permissions to a flight-booking sub-agent. The delegation depth is tracked in the JWT. Revoking the parent cascades to all children.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budget controls&lt;/strong&gt; — Set spending limits per agent. When the budget hits a threshold (50%, 80%), you get an alert. When it's exhausted, the agent is automatically cut off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time event streaming&lt;/strong&gt; — SSE and WebSocket streams for grant creation, token issuance, budget alerts. Build dashboards and monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Policy engine&lt;/strong&gt; — Pluggable authorization backends: builtin rules, OPA, or Cedar. Sync policies from git.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End-user permission dashboard&lt;/strong&gt; — Users can view and revoke agent access from a self-serve dashboard. Embed it in your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&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;# TypeScript / Node.js&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/sdk

&lt;span class="c"&gt;# Python&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex

&lt;span class="c"&gt;# Go&lt;/span&gt;
go get github.com/mishrasanjeev/grantex-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://grantex.dev" rel="noopener noreferrer"&gt;grantex.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://docs.grantex.dev" rel="noopener noreferrer"&gt;docs.grantex.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/mishrasanjeev/grantex" rel="noopener noreferrer"&gt;github.com/mishrasanjeev/grantex&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playground&lt;/strong&gt;: &lt;a href="https://grantex.dev/playground" rel="noopener noreferrer"&gt;grantex.dev/playground&lt;/a&gt; — try it in your browser, no signup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The protocol spec is public and frozen at v1.0. Everything is Apache 2.0. No vendor lock-in — verification is offline via JWKS.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What authorization challenges are you hitting with AI agents? I'd love to hear about your use cases in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>python</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why AI Agents Need Their Own Authorization Protocol (and how we built one)</title>
      <dc:creator>Sanjeev Kumar</dc:creator>
      <pubDate>Sun, 01 Mar 2026 06:48:13 +0000</pubDate>
      <link>https://dev.to/sanjeev_kumar_1755fc90023/why-ai-agents-need-their-own-authorization-protocol-and-how-we-built-one-5gfm</link>
      <guid>https://dev.to/sanjeev_kumar_1755fc90023/why-ai-agents-need-their-own-authorization-protocol-and-how-we-built-one-5gfm</guid>
      <description>&lt;p&gt;AI agents are shipping fast. They book flights, send emails, move money, and deploy code. But here is the uncomfortable truth: most of them operate with all-or-nothing API keys and zero audit trail. If an agent goes rogue, you find out after the damage is done.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://grantex.dev" rel="noopener noreferrer"&gt;Grantex&lt;/a&gt; to fix that.&lt;/p&gt;

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

&lt;p&gt;Every time you click "Sign in with Google" or grant an app access to your calendar, OAuth 2.0 is doing the work. It has been the backbone of delegated authorization for over a decade. So why can't we just use it for AI agents?&lt;/p&gt;

&lt;p&gt;The short answer: agents are not apps.&lt;/p&gt;

&lt;p&gt;OAuth 2.0 was designed for human users clicking "Allow" on a consent screen. It works brilliantly for that. But agents operate autonomously, spawn sub-agents, and chain actions across services. OAuth was never designed for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent identity&lt;/strong&gt; -- agents need their own cryptographic identity, not borrowed user credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation chains&lt;/strong&gt; -- a parent agent granting a sub-agent a narrower set of permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action-level auditing&lt;/strong&gt; -- knowing exactly what an agent did, not just that it authenticated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time revocation&lt;/strong&gt; -- killing a misbehaving agent's access in milliseconds, not minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Four Gaps in Detail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Agent Identity vs. App Identity
&lt;/h3&gt;

&lt;p&gt;OAuth issues tokens to registered applications. An app has a &lt;code&gt;client_id&lt;/code&gt;, a redirect URI, and a set of scopes. This model assumes a fixed, known piece of software.&lt;/p&gt;

&lt;p&gt;AI agents are different. A single orchestrator might spawn dozens of sub-agents at runtime, each with a different purpose. These agents need their own cryptographic identity -- not a shared &lt;code&gt;client_id&lt;/code&gt;. Grantex assigns each agent a DID (Decentralized Identifier) backed by a key pair. The agent's identity is verifiable, rotatable, and independent of the platform it runs on.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scope Delegation Chains
&lt;/h3&gt;

&lt;p&gt;OAuth supports a flat model: a user grants scopes to an app, and that is the end of the story. But agents delegate work to other agents. A "research assistant" agent might call a "web search" sub-agent and a "summarizer" sub-agent, each of which should only get the scopes it actually needs.&lt;/p&gt;

&lt;p&gt;Grantex models this explicitly. When a parent agent delegates to a child, the child's grant token carries &lt;code&gt;parentAgt&lt;/code&gt;, &lt;code&gt;parentGrnt&lt;/code&gt;, and &lt;code&gt;delegationDepth&lt;/code&gt; claims. The child's scopes must be a strict subset of the parent's. This is not a convention -- it is enforced at the protocol level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Root user grants: [files:read, files:write, email:send]
  └─ Parent agent:  [files:read, files:write]  (delegationDepth: 0)
       └─ Child agent:  [files:read]            (delegationDepth: 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the parent's grant is revoked, every child grant in the chain is automatically invalidated.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Real-Time Revocation
&lt;/h3&gt;

&lt;p&gt;OAuth token revocation is defined in RFC 7009, but it is advisory. Resource servers are free to keep accepting a token until it expires. For a 1-hour access token, that is a 1-hour window of exposure.&lt;/p&gt;

&lt;p&gt;With agents performing high-stakes actions autonomously, you cannot afford that window. Grantex supports both offline verification (fast JWT validation) and online verification that checks revocation state in real time. When you revoke a grant, the very next verification call returns &lt;code&gt;valid: false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Action-Level Audit Trails
&lt;/h3&gt;

&lt;p&gt;OAuth gives you an access log at the authorization server. You know when a token was issued and when it was refreshed. You do not know what happened next.&lt;/p&gt;

&lt;p&gt;Grantex includes a first-class audit subsystem. Every action an agent performs can be logged, and the entries are append-only and hash-chained -- each entry references the hash of the previous one, making tampering detectable. You can query the full trail filtered by agent, grant, principal, or time range.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compliance Dimension
&lt;/h2&gt;

&lt;p&gt;This is not just a technical nicety. The EU AI Act (effective August 2025) requires that high-risk AI systems maintain logs of their operation, support human oversight, and provide transparency about their decision-making. Grantex's audit trail, scoped grants, and real-time revocation map directly onto these requirements.&lt;/p&gt;

&lt;p&gt;Similarly, SOC 2 auditors want to see evidence that access is scoped, time-limited, and revocable. Grant tokens with explicit expiration, scope restrictions, and revocation support provide that evidence out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Extend OAuth?
&lt;/h2&gt;

&lt;p&gt;We considered it. The problem is that the primitives do not exist. OAuth has no concept of agent identity, delegation depth, or hash-chained audit logs. Bolting these onto OAuth would mean a constellation of non-standard extensions that no existing library supports.&lt;/p&gt;

&lt;p&gt;Grantex is a clean-sheet protocol that speaks the same language as OAuth where it makes sense (JWTs, JWKs, RS256, scopes, authorization codes) but adds the agent-specific primitives as first-class concepts. If you know OAuth, Grantex will feel familiar. But it will also handle the cases OAuth was never designed for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Looks Like in Code
&lt;/h2&gt;

&lt;p&gt;Here is the full flow in TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Grantex&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@grantex/sdk&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;gx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Grantex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GRANTEX_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Register an agent&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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="s1"&gt;travel-booking-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Books flights and hotels for users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scopes&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="s1"&gt;flights:book&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="s1"&gt;hotels:search&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;// 2. Request authorization from a user&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agent&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="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scopes&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="s1"&gt;flights:book&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="s1"&gt;hotels:search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;callbackUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://app.example.com/callback&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;// → redirect user to auth.consentUrl&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Exchange the authorization code for a grant token&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;callbackCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agent&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Verify the token before acting&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['flights:book', 'hotels:search']&lt;/span&gt;

&lt;span class="c1"&gt;// 5. Log every action to the audit trail&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;gx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agent&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="na"&gt;grantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flight.booked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;airline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Air India&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;420&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 same flow works in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grantex&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Grantex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExchangeTokenParams&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Grantex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GRANTEX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;travel-booking-agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scopes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flights:book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotels:search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scopes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flights:book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotels:search&lt;/span&gt;&lt;span class="sh"&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;# redirect user to auth.consent_url
&lt;/span&gt;
&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;ExchangeTokenParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;callback_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ('flights:book', 'hotels:search')
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Ships Today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol spec v1.0&lt;/strong&gt; (final) -- the full specification is &lt;a href="https://github.com/mishrasanjeev/grantex/blob/main/SPEC.md" rel="noopener noreferrer"&gt;public and frozen&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript SDK&lt;/strong&gt; (&lt;a href="https://www.npmjs.com/package/@grantex/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;@grantex/sdk&lt;/code&gt;&lt;/a&gt;) and &lt;strong&gt;Python SDK&lt;/strong&gt; (&lt;a href="https://pypi.org/project/grantex/" rel="noopener noreferrer"&gt;&lt;code&gt;grantex&lt;/code&gt;&lt;/a&gt;) -- production-ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go SDK&lt;/strong&gt; (&lt;a href="https://pkg.go.dev/github.com/mishrasanjeev/grantex-go" rel="noopener noreferrer"&gt;&lt;code&gt;grantex-go&lt;/code&gt;&lt;/a&gt;) -- production-ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 framework integrations&lt;/strong&gt; -- &lt;a href="https://www.npmjs.com/package/@grantex/langchain" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/@grantex/autogen" rel="noopener noreferrer"&gt;AutoGen&lt;/a&gt;, &lt;a href="https://pypi.org/project/grantex-crewai/" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/@grantex/vercel-ai" rel="noopener noreferrer"&gt;Vercel AI&lt;/a&gt;, &lt;a href="https://pypi.org/project/grantex-openai-agents/" rel="noopener noreferrer"&gt;OpenAI Agents SDK&lt;/a&gt;, &lt;a href="https://pypi.org/project/grantex-adk/" rel="noopener noreferrer"&gt;Google ADK&lt;/a&gt;, an MCP server for Claude Desktop, and &lt;a href="https://www.npmjs.com/package/@grantex/express" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt; + &lt;a href="https://pypi.org/project/grantex-fastapi/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; middleware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI&lt;/strong&gt; (&lt;a href="https://www.npmjs.com/package/@grantex/cli" rel="noopener noreferrer"&gt;&lt;code&gt;@grantex/cli&lt;/code&gt;&lt;/a&gt;) -- manage agents, grants, and tokens from your terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise features&lt;/strong&gt; -- policy engine, SCIM/SSO, anomaly detection, compliance exports, and Stripe billing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full API Reference&lt;/strong&gt; with &lt;a href="https://grantex.mintlify.app/api-reference" rel="noopener noreferrer"&gt;interactive docs&lt;/a&gt; and a &lt;a href="https://github.com/mishrasanjeev/grantex/blob/main/docs/grantex.postman_collection.json" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;Install the SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @grantex/sdk        &lt;span class="c"&gt;# TypeScript / Node.js&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;grantex             &lt;span class="c"&gt;# Python&lt;/span&gt;
go get github.com/mishrasanjeev/grantex-go  &lt;span class="c"&gt;# Go&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @grantex/cli     &lt;span class="c"&gt;# CLI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pick your path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://grantex.dev/docs/quickstart" rel="noopener noreferrer"&gt;Quickstart guide&lt;/a&gt; -- up and running in under 5 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grantex.dev/dashboard/signup" rel="noopener noreferrer"&gt;Sign up for a free account&lt;/a&gt; -- get your API key.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mishrasanjeev/grantex" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; -- star, fork, contribute.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grantex.dev/docs" rel="noopener noreferrer"&gt;Full documentation&lt;/a&gt; -- guides, SDK reference, examples.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grantex.mintlify.app/api-reference" rel="noopener noreferrer"&gt;API Reference&lt;/a&gt; -- all 56 endpoints with schemas.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grantex.dev/docs/protocol/specification" rel="noopener noreferrer"&gt;Protocol specification&lt;/a&gt; -- the full v1.0 spec.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grantex.dev" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; -- project overview.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We believe that as agents become more capable, proper authorization becomes more critical, not less. Grantex is our answer to that challenge.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Grantex is open source (Apache 2.0). If you're building agent systems and care about authorization, we'd love your feedback -- &lt;a href="https://github.com/mishrasanjeev/grantex/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or &lt;a href="https://github.com/mishrasanjeev/grantex" rel="noopener noreferrer"&gt;star the repo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
