Skip to main content

SDK for building tools that integrate with Lyzr Cortex Platform

Project description

Lyzr Cortex SDK for Python

Build tools that integrate with the Lyzr Cortex Platform for bidirectional knowledge flow.

Installation

pip install lyzr-cortex-sdk

# With FastAPI support
pip install lyzr-cortex-sdk[fastapi]

Quick Start

from cortex_sdk import CortexClient

# Auto-configured from environment variables
client = CortexClient()

# Push a document to Knowledge Graph
await client.push(
    type="meeting_transcript",
    id="transcript_123",
    content="Alice: Let's discuss the Q1 roadmap...",
    name="Product Sync - Jan 15",
    scope="team",
    teams=["team_product"],
    metadata={
        "participants": ["alice@example.com", "bob@example.com"],
        "duration_minutes": 45
    }
)

# Query the Knowledge Graph
result = await client.query(
    question="What decisions were made about Q1?",
    filters={"type": ["meeting_transcript"]},
    time_range_days=30
)
print(result.answer)
print(result.sources)

Environment Variables

Variable Description Required
CORTEX_ENABLED Enable/disable integration No (default: true)
CORTEX_API_URL Cortex gateway URL Yes
CORTEX_API_KEY Tool's API key Yes
CORTEX_TOOL_ID Tool identifier Yes
CORTEX_JWT_PUBLIC_KEY RSA public key for JWT validation For embedded mode

FastAPI Integration

from fastapi import FastAPI, Depends
from cortex_sdk import CortexClient
from cortex_sdk.auth import get_current_cortex_user, require_cortex_user
from cortex_sdk.models import CortexUser

app = FastAPI()
cortex = CortexClient()

@app.get("/data")
async def get_data(user: CortexUser | None = Depends(get_current_cortex_user)):
    """Works in both standalone and embedded mode."""
    if user:
        # Embedded mode - use Cortex context
        result = await cortex.query(
            f"Get data for {user.email}",
            user_email=user.email
        )
        return {"data": result.answer, "user": user.email}

    # Standalone mode
    return {"data": "default data"}

@app.get("/protected")
async def protected_endpoint(user: CortexUser = Depends(require_cortex_user)):
    """Only works in embedded mode - requires Cortex auth."""
    return {"email": user.email, "teams": user.team_names}

Graceful Degradation

The SDK operates in no-op mode when Cortex is not available:

client = CortexClient()

if client.enabled:
    # Cortex is available - full functionality
    await client.push(...)
else:
    # Cortex disabled - operations are no-ops
    result = await client.push(...)  # Returns None
    result = await client.query(...)  # Returns empty result

Access Scopes

Scope Who Can See Use For
global Everyone in organization Announcements, shared resources
team Specified team members Projects, deals, team docs
personal Only the creator Notes, drafts, personal items

API Reference

CortexClient

push(type, id, content, scope="global", teams=None, metadata=None)

Push a document to the Knowledge Graph.

  • type: Document type (e.g., "meeting_transcript")
  • id: Unique identifier
  • content: Text content for RAG indexing
  • name: Display name for the document
  • url: URL to view document in source tool
  • scope: "global", "team", or "personal"
  • teams: Team IDs if scope is "team"
  • metadata: Additional metadata dict

query(question, filters=None, time_range_days=None, max_results=10, user_email=None)

Query the Knowledge Graph.

  • question: Natural language query
  • filters: Filter dict (e.g., {"type": ["meeting_transcript"]})
  • time_range_days: Limit to recent documents
  • max_results: Maximum results
  • user_email: User email for access-scoped queries

Returns CortexQueryResult with answer and sources.

get_user_context(user_email)

Get user context for access control.

Returns CortexUser with teams, permissions, etc.

share_document(document_external_id, shared_by_email, shared_with_email, ...)

Share a document with another user in the organization.

  • document_external_id: External ID of the document to share
  • shared_by_email: Email of the user sharing
  • shared_with_email: Email of the recipient
  • document_name: Display name for the shared document
  • content: Document content
  • external_url: URL to view the document
  • metadata: Additional metadata dict

get_org_users(exclude_email=None)

Get list of users in the tool's organization.

  • exclude_email: Email to exclude from results (typically the current user)

Returns list of user dicts with id, email, full_name, avatar_url.

Embedded Mode Authentication (Production)

When your tool runs inside a Cortex iframe, the frontend receives the user's OGI JWT via the CORTEX_INIT postMessage. To ensure authentication works in production (where reverse proxies may strip custom headers), your tool should send both custom Cortex headers and the standard Authorization header.

Frontend: Passing Auth Headers

import { useCortex } from '@/lib/cortex';

function useAuthHeaders() {
  const { isEmbedded, user, token } = useCortex();

  const getHeaders = (): Record<string, string> => {
    if (isEmbedded && user) {
      const headers: Record<string, string> = {
        // Custom headers — work locally, may be stripped by production proxies
        'X-Cortex-Embedded': 'true',
        'X-Cortex-User-Email': user.email,
      };
      // Standard header — survives all reverse proxies / CDNs / ALBs
      if (token) {
        headers['Authorization'] = `Bearer ${token}`;
      }
      return headers;
    }
    // Standalone mode: use your own JWT from localStorage
    const jwt = localStorage.getItem('token');
    return jwt ? { Authorization: `Bearer ${jwt}` } : {};
  };

  return { getHeaders };
}

Backend: Accepting Both Auth Modes

from fastapi import Depends, Header, HTTPException
import jwt

async def get_current_user(
    authorization: str = Header(None),
    x_cortex_embedded: str = Header(None),
    x_cortex_user_email: str = Header(None),
):
    # Mode 1: Cortex embedded — custom headers (local / non-proxied)
    if x_cortex_embedded == "true" and x_cortex_user_email:
        return x_cortex_user_email

    # Mode 2: Bearer token — works through all proxies
    if authorization and authorization.startswith("Bearer "):
        token = authorization.split(" ", 1)[1]
        try:
            # Try your tool's own JWT secret first
            payload = jwt.decode(token, YOUR_SECRET_KEY, algorithms=["HS256"])
            return payload["sub"]
        except jwt.InvalidTokenError:
            pass
        try:
            # Fall back to OGI JWT (CORTEX_JWT_PUBLIC_KEY)
            payload = jwt.decode(token, CORTEX_JWT_PUBLIC_KEY, algorithms=["HS256"])
            return payload.get("email") or payload.get("sub")
        except jwt.InvalidTokenError:
            pass

    raise HTTPException(status_code=401, detail="Not authenticated")

Why Both Headers?

Header Works Locally Works in Production Notes
X-Cortex-Embedded Yes Maybe Custom headers may be stripped by CDN/ALB/nginx
X-Cortex-User-Email Yes Maybe Same risk as above
Authorization: Bearer Yes Yes Standard HTTP header, always forwarded

Production flow:

  1. User opens your tool inside Cortex iframe
  2. Cortex sends CORTEX_INIT with { user, theme, token } via postMessage
  3. Your frontend sends API requests with both custom headers AND Authorization: Bearer {token}
  4. Your backend tries custom headers first (fast path), falls back to JWT decode (proxy-safe path)

Environment Variables

Variable Description
CORTEX_JWT_PUBLIC_KEY OGI's JWT signing key — must match OGI server's JWT_SECRET_KEY

Set this in your tool's .env:

CORTEX_JWT_PUBLIC_KEY=your-ogi-jwt-secret-key

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lyzr_cortex_sdk-0.1.2.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lyzr_cortex_sdk-0.1.2-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file lyzr_cortex_sdk-0.1.2.tar.gz.

File metadata

  • Download URL: lyzr_cortex_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for lyzr_cortex_sdk-0.1.2.tar.gz
Algorithm Hash digest
SHA256 d518be50a86da6cfd98b6efb245f23e54f219591c90211ccb15c19ed1b6f185c
MD5 2609f48e9142e5a342239287475255b1
BLAKE2b-256 06b3afc23c583ab27978b5f04d2da8471bf578a28068c0856f5e0231b669630c

See more details on using hashes here.

File details

Details for the file lyzr_cortex_sdk-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for lyzr_cortex_sdk-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1cfab2443ca1fdc77d35e0ecb1aaad7c62463115bd7d2320efb7299c86149fe8
MD5 901f69d7a8602bb69152ae9d63805bc1
BLAKE2b-256 9884b46ada162dce7af9e82614d7ec862484a76f2e2e9e0538b2d842a5a5709e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page