Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

8 Commits

Repository files navigation

iGPT Python SDK (igptai)

Official Python SDK for the iGPT API.

Requirements

  • Python >= 3.8

Install

pip install igptai

Authentication

All requests use a Bearer token:

  • Header: Authorization: Bearer <IGPT_API_KEY>

Store keys in a secret manager or environment variables.

Quick start

The typical flow when using iGPT is:

  1. Connect datasources (per user)
  2. Retrieve answers using the connected context

Connect a datasource

This example starts an authorization flow to connect a user’s datasource.
The response includes a URL the user must open to complete authorization.

fromigptaiimportIGPTigpt=IGPT(api_key="IGPT_API_KEY")
res=igpt.connectors.authorize(user="user_123", service="spike", scope="messages")
ifresisNone:
print("No response / request failed")
elifres.get("error"):
print("Connection error:", res)
else:
print("Open this URL to authorize:", res.get("url"))

Run with recall.run()

After connecting a datasource, you can run an agentic request scoped to that user.

A run can retrieve relevant context, use available tools, and generate a response based on the connected datasource.

fromigptaiimportIGPTigpt=IGPT(api_key="IGPT_API_KEY", user="user_123") # optional default userres=igpt.recall.run(input="Summarize key risks, decisions, and next steps from this week's meetings.")
ifresisNone:
print("No response / request failed")
elifres.get("error"):
# No-throw design: handle errors via return valueprint("iGPT error:", res)
else:
print("iGPT response:", res)

Services and routing

Calls map to API routes automatically, for example:

  • igpt.recall.run(...)POST /recall/run
  • igpt.recall.search(...)POST /recall/search
  • igpt.recall.ask(...)POST /recall/ask
  • igpt.datasources.list(...)POST /datasources/list
  • igpt.datasources.disconnect(...)POST /datasources/disconnect
  • igpt.connectors.authorize(...)POST /connectors/authorize

Connectors

connectors.authorize()

Authorize, connect, and start indexing a new datasource.

Parameters

  • service (string, required): Service provider identifier (e.g., "spike").
  • scope (string, required): Space-delimited scopes (e.g., "messages").
  • user (string, optional if set in constructor): Unique user identifier.
  • redirect_uri (string, optional): Redirect URL after authorization completes.
  • state (string, optional): Application state (returned after redirect).

Example: start an authorization flow

res=igpt.connectors.authorize(service="spike", scope="messages", user="user_123", redirect_uri="https://yourapp.com/callback", state="optional_state")
print(res)

Agentic Run

recall.run()

Generate an agentic response based on the provided input and the end-user’s connected context.

A run may perform multiple reasoning turns, call internal tools, retrieve relevant sources, and stream the final response as it is generated.

  • input (string, required): The prompt or question to process.
  • user (string, optional if set in constructor): A unique identifier representing your end-user.
  • stream (boolean, optional, default: False): When True, returns an iterable of run events.
  • quality (string, optional): Context engineering quality (e.g., "cef-4-high").
  • reasoning_effort (string, optional): Controls the reasoning effort (e.g., "low", "medium", or "high").
  • output_format (string | object, optional):
    • "text" - Plain-text output and the default format.
    • "json" - JSON output.
    • { schema: <JSON Schema> } - Structured output that follows a JSON Schema.
  • instructions (string, optional): Additional instructions controlling the response behavior, style, constraints, or structure.

Example: text output

resp=client.recall.run(
input="Summarize my unread emails from the last 7 days.",
quality="cef-4-high",
reasoning_effort="high",
output_format="text",
instructions="Be concise and highlight anything that needs a response."
)
print(resp)

Example: JSON output

resp=client.recall.run(
input="Summarize my last meeting and return the title and summary.",
output_format="json"
)
print(resp)

Example: structured output with JSON Schema

Use a schema to produce a consistent, machine-readable response.

output_format= {
"type": "json_schema",
"name": "action_items_result",
"strict": True,
"schema": {
"type": "object",
"properties": {
"action_items": {
"type": "array",
"description": "List of action items",
"items": {
"type": "object",
"properties": {
"title": {"type": "string", "description": "Short summary of the action item"},
"owner": {"type": "string", "description": "Person responsible for the action item"},
"due_date": {"type": "string", "description": "Expected completion date, ISO 8601 (YYYY-MM-DD)"}
},
"required": ["title", "owner", "due_date"],
"additionalProperties": False
}
}
},
"required": ["action_items"],
"additionalProperties": False
}
}
resp=client.recall.run(
input="Extract all action items from yesterday’s board meeting.",
quality="cef-4-high",
reasoning_effort="high",
output_format=output_format
)
print(resp)

Streaming

For streaming responses, set stream=True.

The SDK returns an iterable that yields parsed event dictionaries. Each event represents a step in the run lifecycle.

forchunkinclient.recall.run(input="Summarize my unread emails from the last 7 days.", stream=True, quality="cef-1-normal"):
print(chunk, end="", flush=True)

Stream lifecycle

A streamed run starts with run.start and ends with run.done.

Everything between these two events belongs to the same run.

A run may contain one or more turns. Each turn may include reasoning, tool calls, or output generation.

run.start
run.turn.start
run.reasoning_item.start
run.reasoning_item.done
run.tool_call_item
run.turn.done
run.tool_call_output_item
run.turn.start
run.reasoning_item.start
run.reasoning_summary_part.start
run.reasoning_summary_part.done
run.reasoning_item.done
run.output_item.start
run.output_text.delta
run.output_text.delta
...
run.output_item.done
run.turn.done
run.done

This lifecycle is representative. The exact number of turns, reasoning items, summary parts, tool calls, and output deltas depends on the request.

Important relationships:

  • run.start opens the complete run.
  • run.done closes the complete run.
  • seq defines the exact order of all events in the run.
  • turn identifies the model turn being processed.
  • callId connects a tool call with its corresponding tool result.
  • run.output_text.delta contains partial output text.
  • run.output_item.done contains the complete assistant message.
  • run.done contains the final run output, usage, duration, and aggregated source metadata.
  • A run.tool_call_output_item may appear between the turn that requested the tool and the next turn that processes its result.
  • Reasoning summary events are optional and may not appear in every turn.

Stream event object shapes

The following JSON objects document the expected key types. Values such as "string", "number", "object", and "array<object>" describe the value type and are not literal API response values.

run.start

{
"type": "run.start",
"seq": "number",
"id": "string",
"timestamp": "number",
"context": {
"quality": "string",
"reasoning_effort": "string",
"indexed": "number",
"datasources": [
{
"id": "string",
"service": "string",
"type": "string",
"status": "string",
"title": "string",
"subtitle": "string",
"progress": "number",
"newest": "number",
"oldest": "number"
}
]
},
"output_format": "string | object"
}

run.turn.start

{
"type": "run.turn.start",
"seq": "number",
"turn": "number"
}

run.reasoning_item.start

{
"type": "run.reasoning_item.start",
"seq": "number",
"item": {
"type": "reasoning"
}
}

run.reasoning_item.done

{
"type": "run.reasoning_item.done",
"seq": "number",
"item": {
"type": "reasoning",
"content": "array",
"summary": [
{
"type": "summary_text",
"text": "string"
}
]
}
}

run.reasoning_summary_part.start

{
"type": "run.reasoning_summary_part.start",
"seq": "number"
}

run.reasoning_summary_part.done

{
"type": "run.reasoning_summary_part.done",
"seq": "number",
"text": "string"
}

run.tool_call_item

{
"type": "run.tool_call_item",
"seq": "number",
"item": {
"type": "function_call",
"arguments": "string",
"name": "string",
"callId": "string"
}
}

run.turn.done

{
"type": "run.turn.done",
"seq": "number",
"turn": "number"
}

run.tool_call_output_item

{
"type": "run.tool_call_output_item",
"seq": "number",
"item": {
"type": "function_call_result",
"name": "string",
"callId": "string",
"metadata": {
"sources": [
{
"id": "string",
"type": "string",
"timestamp": "number",
"provider": "string",
"picture": "string",
"title": "string"
}
]
}
}
}

run.output_item.start

{
"type": "run.output_item.start",
"seq": "number",
"item": {
"type": "message"
}
}

run.output_text.delta

{
"type": "run.output_text.delta",
"seq": "number",
"delta": "string"
}

run.output_item.done

{
"type": "run.output_item.done",
"seq": "number",
"item": {
"type": "message",
"content": [
{
"type": "output_text",
"text": "string"
}
],
"role": "assistant"
}
}

run.done

{
"type": "run.done",
"id": "string",
"seq": "number",
"timestampStart": "number",
"timestamp": "number",
"duration": "number",
"output": "string | object | array | null",
"usage": {
"input_tokens": "number",
"output_tokens": "number",
"total_tokens": "number"
},
"metadata": {
"sources": [
{
"id": "string",
"type": "string",
"timestamp": "number",
"provider": "string",
"picture": "string",
"title": "string"
}
]
}
}

Understanding the stream keys

Common event keys

KeyTypeDescription
typestringIdentifies what happened in the stream, for example "run.start" or "run.output_text.delta".
seqnumberMonotonically increasing sequence number defining the event’s exact order within the run.
idstringUnique identifier for the complete run. It appears on run.start and run.done.
timestampnumberUnix timestamp in milliseconds for run-level events.
timestampStartnumberUnix timestamp in milliseconds indicating when the completed run began.
durationnumberTotal run duration in milliseconds.

Run context keys

KeyTypeDescription
contextobjectContext configuration and datasource state used by the run.
context.qualitystringContext engineering quality used for the run.
context.reasoning_effortstringReasoning effort selected for the run.
context.indexednumberNumber of indexed datasources available to the run.
context.datasourcesarray<object>Connected and indexed datasources available to the run.
output_formatstring | objectOutput format selected for the run.

Datasource keys

KeyTypeDescription
idstringUnique datasource identifier.
servicestringService that owns the datasource.
typestringDatasource type, such as "spike/messages".
statusstringCurrent datasource status, such as "enabled".
titlestringHuman-readable datasource name.
subtitlestringAdditional datasource information, such as the connected account.
progressnumberIndexing progress, generally represented from 0 to 100.
newestnumberUnix timestamp in seconds for the newest indexed item.
oldestnumberUnix timestamp in seconds for the oldest indexed item.

Turn and reasoning keys

KeyTypeDescription
turnnumberSequential model turn number inside the run.
itemobjectThe nested item carried by the event.
item.typestringIdentifies the nested item, such as "reasoning", "function_call", or "message".
item.contentarrayReasoning content blocks. This may be empty when only a summary is exposed.
item.summaryarray<object>Reasoning summary items exposed by the API.
textstringComplete reasoning-summary text when a summary part finishes.

Tool-call keys

KeyTypeDescription
item.namestringName of the requested tool or function.
item.argumentsstringJSON-encoded function arguments. Use json.loads() to convert the string into a Python dictionary.
item.callIdstringUnique identifier connecting a function call with its corresponding result.
item.metadataobjectMetadata returned by the completed tool call.
item.metadata.sourcesarray<object>Sources returned or used by the tool call.

Example of parsing tool arguments:

forchunkinclient.recall.run(
input="Summarize my emails from last 2 days",
stream=True,
quality="cef-1-normal",
):
ifchunk.get("type") =="run.tool_call_item":
item=chunk["item"]
args=json.loads(item["arguments"])
print("\nTool:", item["name"])
print("Arguments:", args)
print("Call ID:", item["callId"])
print()

Output keys

KeyTypeDescription
deltastringPartial output fragment. Concatenate all deltas in seq order to construct the streamed response.
item.contentarray<object>Complete output content blocks when the assistant message finishes.
item.rolestringRole that generated the message. For assistant output, the value is "assistant".
outputstring | object | array | nullFinal output of the complete run. Its shape depends on output_format.
usageobjectToken usage for the complete run.
usage.input_tokensnumberNumber of tokens used as model input.
usage.output_tokensnumberNumber of tokens generated by the model.
usage.total_tokensnumberTotal number of input and output tokens.
metadataobjectFinal metadata collected for the complete run.
metadata.sourcesarray<object>Aggregated sources used during the run.

Source keys

KeyTypeDescription
idstringUnique source identifier.
typestringSource type, such as "message".
timestampnumberUnix timestamp in seconds associated with the source.
providerstringPerson, service, or organization that provided the source.
picturestringSource image or avatar URL.
titlestringHuman-readable source title.

Consuming stream events

foreventinclient.recall.run(
input="Summarize my unread emails from the last 7 days.",
stream=True,
):
event_type=event.get("type")
ifevent_type=="run.start":
print("Run started:", event["id"])
print("Datasources:", event["context"]["datasources"])
elifevent_type=="run.turn.start":
print("Turn started:", event["turn"])
elifevent_type=="run.tool_call_item":
item=event["item"]
print("Calling tool:", item["name"])
print("Call ID:", item["callId"])
print("Arguments:", json.loads(item["arguments"]))
elifevent_type=="run.tool_call_output_item":
item=event["item"]
print("Tool completed:", item["name"])
print("Sources:", item.get("metadata", {}).get("sources"))
elifevent_type=="run.output_text.delta":
print(event["delta"], end="", flush=True)
elifevent_type=="run.output_item.done":
print("\nComplete message:", event["item"]["content"])
elifevent_type=="run.done":
print("\nRun completed:", event["id"])
print("Duration:", event.get("duration"))
print("Usage:", event.get("usage"))
print("Final output:", event.get("output"))

Recall

recall.search()

Search in connected datasources.

Parameters

  • query (string, optional): Search query to execute.
  • user (string, optional if set in constructor): Unique user identifier.
  • date_from (string, optional): Start date filter (YYYY-MM-DD).
  • date_to (string, optional): End date filter (YYYY-MM-DD).
  • filter_people (string, optional): Restrict results to content involving specific people.
  • max_results (number, optional): Limit number of results (e.g., 50).

Example: simple search

res=igpt.recall.search(query="board meeting notes")
print(res)

Example: search by people

res=igpt.recall.search(query="budget allocation", filter_people="Emma", max_results=25)
print(res)

Example: date-bounded search

res=igpt.recall.search(query="budget allocation", date_from="2026-01-01", date_to="2026-01-31", max_results=25)
print(res)

recall.ask()

Generate a response based on the input and related context.

Parameters

  • input (string, required): The prompt/question to ask.
  • user (string, optional if set in constructor): Unique user identifier.
  • stream (boolean, optional, default: false): If true, returns an async iterable stream.
  • quality (string, optional): Context engineering quality (default: "cef-1-normal"). Read more.
  • output_format (string | object, optional):
    • "text" (default)
    • "json"
    • { schema: <JSON Schema> } to enforce a structured output

Example: text output

res=igpt.recall.ask(input="Summarize my last meeting in 5 bullet points.", quality="cef-1-normal", output_format="text")
print(res)

Example: JSON output

res=igpt.recall.ask(input="Return a JSON object with { title, summary } for my last meeting.", output_format="json")
print(res)

Example: Structured output with JSON Schema

Use a schema to get consistent, machine-validated structure.

output_format= {
"strict": True,
"schema": {
"type": "object",
"properties": {
"action_items": {
"type": "array",
"description": "List of action items",
"items": {
"type": "object",
"properties": {
"title": { "type": "string", "description": "Short summary of the action item" },
"owner": { "type": "string", "description": "Person responsible for the action item" },
"due_date": { "type": "string", "format": "date", "description": "Expected completion date" }
},
"required": ["title", "owner", "due_date"],
"additionalProperties": False
}
}
},
"required": ["action_items"],
"additionalProperties": False
}
}
res=igpt.recall.ask(output_format=output_format, input="Extract all action items from yesterday’s board meeting.", quality: "cef-1-normal")
print(res)

Example response (schema)

{
"action_items": [
{
"title": "Approve revised Q1 budget allocation",
"owner": "Board of Directors",
"due_date": "2026-01-15"
},
{
"title": "Approve final FY2026 strategic priorities",
"owner": "Board of Directors",
"due_date": "2026-01-31"
}
]
}

Streaming (SSE)

For streaming responses, set stream=True. The SDK returns an iterable that yields parsed JSON chunks.

Streaming is designed to be resilient: if the stream breaks due to connectivity, the iterator yields an error chunk and finishes rather than throwing.

Parameters (streaming-specific)

  • stream must be True
  • Other parameters are the same as recall.ask

Example: basic streaming

stream=igpt.recall.ask(input="Summarize my last meeting.", stream=True)
forchunkinstream:
if (isinstance(chunk, dict) andchunk.get("error")):
print("Stream chunk error:", chunk)
breakprint("chunk:", chunk)

Datasources

datasources.list()

List datasources and indexing status.

Parameters

  • user (string, optional if set in constructor): Unique user identifier.

Example

res=igpt.datasources.list()
print(res)

datasources.disconnect()

Disconnect a datasource and remove indexed data.

Parameters

  • id (string, required): Datasource ID to disconnect (e.g., "service/id/type").
  • user (string, optional if set in constructor): Unique user identifier.

Example

resp=igpt.datasources.disconnect(id="service/id/type")
print(resp)

Advanced Configuration

igpt=IGPT(
api_key="IGPT_API_KEY", # requireduser="default_user_id", # optional default userbase_url="https://api.igpt.ai/v1", # optional overridemax_retries=3, # optional: network retriesbackoff_factor=2, # optional: exponential backoff factorbackoff_base=100# optional: initial retry delay (ms)
)

Constructor options

  • api_key (string, required): Your iGPT API key.
  • user (string, optional): Default user identifier. If provided, you can omit user in method calls.
  • base_url (string, optional): Override API base URL (default: https://api.igpt.ai/v1).
  • max_retries (number, optional): Retry attempts (default: 3).
  • backoff_base (number, optional): Initial retry delay in milliseconds (default: 100).
  • backoff_factor (number, optional): Exponential backoff multiplier (default: 2).

Error handling

The SDK does not throw exceptions for request or stream failures.
Instead, it returns (or yields) normalized error objects with a consistent shape:

{ error: string }

Client errors

Errors originating from the client environment:

  • { error: "network_error" } - A network-level failure occurred (timeout, DNS issue, offline).
  • { error: "request_aborted" } - The request was explicitly aborted by the caller.

Server errors

Errors returned by the API:

  • { error: "auth" } - Authentication failed due to missing, invalid, or expired credentials.
  • { error: "params" } - The request parameters were invalid or malformed.

Security & compliance

Resources

License

MIT