iGPT Python SDK (igptai)
Official Python SDK for the iGPT API.
- Website: https://www.igpt.ai
- Documentation: https://docs.igpt.ai
- Playground: https://igpt.ai/hub/playground/
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:
- Connect datasources (per user)
- 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.
from igptai import IGPT
igpt = IGPT(api_key="IGPT_API_KEY")
res = igpt.connectors.authorize(user="user_123", service="spike", scope="messages")
if res is None:
print("No response / request failed")
elif res.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.
from igptai import IGPT
igpt = IGPT(api_key="IGPT_API_KEY", user="user_123") # optional default user
res = igpt.recall.run(input="Summarize key risks, decisions, and next steps from this week's meetings.")
if res is None:
print("No response / request failed")
elif res.get("error"):
# No-throw design: handle errors via return value
print("iGPT error:", res)
else:
print("iGPT response:", res)
Services and routing
Calls map to API routes automatically, for example:
igpt.recall.run(...)→POST /recall/runigpt.recall.search(...)→POST /recall/searchigpt.recall.ask(...)→POST /recall/askigpt.datasources.list(...)→POST /datasources/listigpt.datasources.disconnect(...)→POST /datasources/disconnectigpt.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): WhenTrue, 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.
for chunk in client.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.startopens the complete run.run.donecloses the complete run.seqdefines the exact order of all events in the run.turnidentifies the model turn being processed.callIdconnects a tool call with its corresponding tool result.run.output_text.deltacontains partial output text.run.output_item.donecontains the complete assistant message.run.donecontains the final run output, usage, duration, and aggregated source metadata.- A
run.tool_call_output_itemmay 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
| Key | Type | Description |
|---|---|---|
type |
string |
Identifies what happened in the stream, for example "run.start" or "run.output_text.delta". |
seq |
number |
Monotonically increasing sequence number defining the event’s exact order within the run. |
id |
string |
Unique identifier for the complete run. It appears on run.start and run.done. |
timestamp |
number |
Unix timestamp in milliseconds for run-level events. |
timestampStart |
number |
Unix timestamp in milliseconds indicating when the completed run began. |
duration |
number |
Total run duration in milliseconds. |
Run context keys
| Key | Type | Description |
|---|---|---|
context |
object |
Context configuration and datasource state used by the run. |
context.quality |
string |
Context engineering quality used for the run. |
context.reasoning_effort |
string |
Reasoning effort selected for the run. |
context.indexed |
number |
Number of indexed datasources available to the run. |
context.datasources |
array<object> |
Connected and indexed datasources available to the run. |
output_format |
string | object |
Output format selected for the run. |
Datasource keys
| Key | Type | Description |
|---|---|---|
id |
string |
Unique datasource identifier. |
service |
string |
Service that owns the datasource. |
type |
string |
Datasource type, such as "spike/messages". |
status |
string |
Current datasource status, such as "enabled". |
title |
string |
Human-readable datasource name. |
subtitle |
string |
Additional datasource information, such as the connected account. |
progress |
number |
Indexing progress, generally represented from 0 to 100. |
newest |
number |
Unix timestamp in seconds for the newest indexed item. |
oldest |
number |
Unix timestamp in seconds for the oldest indexed item. |
Turn and reasoning keys
| Key | Type | Description |
|---|---|---|
turn |
number |
Sequential model turn number inside the run. |
item |
object |
The nested item carried by the event. |
item.type |
string |
Identifies the nested item, such as "reasoning", "function_call", or "message". |
item.content |
array |
Reasoning content blocks. This may be empty when only a summary is exposed. |
item.summary |
array<object> |
Reasoning summary items exposed by the API. |
text |
string |
Complete reasoning-summary text when a summary part finishes. |
Tool-call keys
| Key | Type | Description |
|---|---|---|
item.name |
string |
Name of the requested tool or function. |
item.arguments |
string |
JSON-encoded function arguments. Use json.loads() to convert the string into a Python dictionary. |
item.callId |
string |
Unique identifier connecting a function call with its corresponding result. |
item.metadata |
object |
Metadata returned by the completed tool call. |
item.metadata.sources |
array<object> |
Sources returned or used by the tool call. |
Example of parsing tool arguments:
for chunk in client.recall.run(
input="Summarize my emails from last 2 days",
stream=True,
quality="cef-1-normal",
):
if chunk.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
| Key | Type | Description |
|---|---|---|
delta |
string |
Partial output fragment. Concatenate all deltas in seq order to construct the streamed response. |
item.content |
array<object> |
Complete output content blocks when the assistant message finishes. |
item.role |
string |
Role that generated the message. For assistant output, the value is "assistant". |
output |
string | object | array | null |
Final output of the complete run. Its shape depends on output_format. |
usage |
object |
Token usage for the complete run. |
usage.input_tokens |
number |
Number of tokens used as model input. |
usage.output_tokens |
number |
Number of tokens generated by the model. |
usage.total_tokens |
number |
Total number of input and output tokens. |
metadata |
object |
Final metadata collected for the complete run. |
metadata.sources |
array<object> |
Aggregated sources used during the run. |
Source keys
| Key | Type | Description |
|---|---|---|
id |
string |
Unique source identifier. |
type |
string |
Source type, such as "message". |
timestamp |
number |
Unix timestamp in seconds associated with the source. |
provider |
string |
Person, service, or organization that provided the source. |
picture |
string |
Source image or avatar URL. |
title |
string |
Human-readable source title. |
Consuming stream events
for event in client.recall.run(
input="Summarize my unread emails from the last 7 days.",
stream=True,
):
event_type = event.get("type")
if event_type == "run.start":
print("Run started:", event["id"])
print("Datasources:", event["context"]["datasources"])
elif event_type == "run.turn.start":
print("Turn started:", event["turn"])
elif event_type == "run.tool_call_item":
item = event["item"]
print("Calling tool:", item["name"])
print("Call ID:", item["callId"])
print("Arguments:", json.loads(item["arguments"]))
elif event_type == "run.tool_call_output_item":
item = event["item"]
print("Tool completed:", item["name"])
print("Sources:", item.get("metadata", {}).get("sources"))
elif event_type == "run.output_text.delta":
print(event["delta"], end="", flush=True)
elif event_type == "run.output_item.done":
print("\nComplete message:", event["item"]["content"])
elif event_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): Iftrue, 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)
streammust beTrue- Other parameters are the same as
recall.ask
Example: basic streaming
stream = igpt.recall.ask(input="Summarize my last meeting.", stream=True)
for chunk in stream:
if (isinstance(chunk, dict) and chunk.get("error")):
print("Stream chunk error:", chunk)
break
print("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", # required
user="default_user_id", # optional default user
base_url="https://api.igpt.ai/v1", # optional override
max_retries=3, # optional: network retries
backoff_factor=2, # optional: exponential backoff factor
backoff_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 omituserin 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
- Use a secure secret manager for
IGPT_API_KEY(do not hardcode keys in source control). - Ensure user identifiers (
user) align with your internal identity and access model. - For policy and legal references:
- Privacy Policy: https://www.igpt.ai/privacy-policy/
- Terms & Conditions: https://www.igpt.ai/terms-and-conditions/
Resources
- Docs: https://docs.igpt.ai
- Playground: https://igpt.ai/hub/playground/
- Book a demo: https://www.igpt.ai/contact-sales/
- Contact: hello@igpt.ai
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file igptai-1.2.0.tar.gz.
File metadata
- Download URL: igptai-1.2.0.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e64a52593975db413107c89ea2be2c9d955902d5c5ff9e89dc3fa67fcee7186
|
|
| MD5 |
642b611f34d98ae238dd0b384e09327a
|
|
| BLAKE2b-256 |
a3a3aa54cf7bae12edf024ba368c4c829454136a4fe794ac2d767a52dfd35a97
|
File details
Details for the file igptai-1.2.0-py3-none-any.whl.
File metadata
- Download URL: igptai-1.2.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42ea70dc738821c0f85c242c63d6d16a1860773280b05979498e9a65eef45479
|
|
| MD5 |
4082883c4df0e70850e303e79146cb87
|
|
| BLAKE2b-256 |
6aae88eb47c5b94c54f84b8926e00b12a819a2f05df156f85b4bf59db6148af7
|