Quick Start#

Installation#

Install the base package plus the provider extras you need:

# Base (no provider)
pip install core-genai

# Individual providers
pip install "core-genai[claude]"
pip install "core-genai[chatgpt]"
pip install "core-genai[gemini]"
pip install "core-genai[grok]"

# Multiple providers at once
pip install "core-genai[gemini,claude,chatgpt,grok]"

# Development (includes all test/lint tools)
pip install -e ".[dev]"

Usage#

All agents share the same interface. Pick a provider, create an agent, and call analyze.

Synchronous#

Wrap any agent with SyncWrapper from core-mixins to use it synchronously without managing an event loop yourself:

from core_mixins.decorators.async_ import SyncWrapper
from core_genai.interfaces import IAgent

agent = IAgent.create_agent("ClaudeAgent", api_key="YOUR_API_KEY")

with SyncWrapper(agent) as sync_agent:
    output = sync_agent.analyze(
        model="claude-haiku-4-5",
        prompt="Explain how AI works in a few words.",
    )
    print(agent.get_text(output))

Switching providers#

Because every agent implements the same IAgent interface you can swap providers by changing a single line:

# Gemini
agent = IAgent.create_agent("GeminiAgent", api_key=GEMINI_KEY)
output = await agent.analyze(model="gemini-2.0-flash", prompt=PROMPT)

# Claude
agent = IAgent.create_agent("ClaudeAgent", api_key=CLAUDE_KEY)
output = await agent.analyze(model="claude-haiku-4-5", prompt=PROMPT)

# ChatGPT
agent = IAgent.create_agent("ChatGPTAgent", api_key=OPENAI_KEY)
output = await agent.analyze(model="gpt-4o-mini", prompt=PROMPT)

# Grok
agent = IAgent.create_agent("GrokAgent", api_key=XAI_KEY)
output = await agent.analyze(model="grok-3-mini", prompt=PROMPT)

# The rest of the code is identical for all providers:
print(agent.get_text(output))
print(agent.get_cost(output))
print(agent.get_metadata(output))

Usage metadata#

get_metadata() returns a normalized UsageMetadata dict regardless of provider:

meta = agent.get_metadata(output)

print(meta["input_tokens"])         # tokens sent
print(meta["output_tokens"])        # tokens received
print(meta["total_tokens"])         # combined
print(meta["cost_usd"])             # estimated USD cost

# Optional fields (present only when the provider reports them):
meta.get("cached_tokens")           # cache read/hit tokens (Gemini, Claude)
meta.get("cache_creation_tokens")   # cache write tokens (Claude only)
meta.get("reasoning_tokens")        # thinking tokens (Gemini only)

Batch jobs#

Gemini, Claude, ChatGPT, and Grok all implement the IScheduler interface for large-scale asynchronous inference at reduced cost (~50% discount on most providers).

Each agent accepts simple ScheduledJobMetadata request objects; the provider-specific JSONL serialization is handled internally.

import asyncio
from core_genai.interfaces import IAgent, IScheduler
from core_genai.chatgpt.agent import BatchRequest

agent = IAgent.create_agent("ChatGPTAgent", api_key="YOUR_API_KEY")

requests = [
    BatchRequest(custom_id="req-0", prompt=[{"role": "user", "content": "What is ML?"}]),
    BatchRequest(custom_id="req-1", prompt=[{"role": "user", "content": "What is a neural net?"}]),
]

async def main():
    job = await agent.schedule_job(requests=requests, model="gpt-4o-mini")
    print(job["job_id"])

    # Poll until done
    while True:
        state = await agent.check_job_status(job["job_id"])
        if state in agent.TERMINAL_STATES:
            break
        await asyncio.sleep(30)

    result = await agent.extract_job_results(job["job_id"])
    for item in result["results"] or []:
        print(item)

asyncio.run(main())

The same pattern works for Gemini, Claude, and Grok by swapping the agent and request type. Results are returned via ScheduledJobResponse with a normalized job_id, results, error, and state field.