Python SDK
Official Python SDK for AI Teammate.v0.4.0
End-User bookmarks, authentication, Google OAuth, agent documents (RAG)
Installation
pip install ai-teammate
Getting Started
Sign up at ai-teammate.net (Google / Kakao OAuth)
Generate API key in Settings → API Keys tab (format: at_xxxx...)
Create your first agent and start chatting with the code below
from ai_teammate import AITeammate
client = AITeammate(api_key="at_your_key_here")
# Create an agent
agent = client.agents.create(
name="My First Agent",
system_prompt="You are a helpful assistant that speaks Korean.",
)
print(f"Agent created: {agent.id}")
# Chat with the agent
response = client.chat("Hello!", agent_id=agent.id)
print(response.content)Agent Management
# List all agents
agents = client.agents.list()
for agent in agents:
print(f"{agent.name} ({agent.id})")
# Create an agent
agent = client.agents.create(
name="My Assistant",
system_prompt="You are a helpful assistant.",
)
# Update an agent
agent = client.agents.update(
agent_id="abc123",
name="Updated Name",
system_prompt="New prompt",
)
# Delete an agent
client.agents.delete("abc123")Agent Documents (RAG)
Upload documents to an agent so all users can leverage that knowledge in conversations.
# Upload a document (pdf, txt, md, docx, csv)
doc = client.agents.upload_document("abc123", "./menu.txt")
print(f"Uploaded: {doc.filename} ({doc.chunk_count} chunks)")
# List documents
docs = client.agents.list_documents("abc123")
for d in docs:
print(f"{d.filename} ({d.chunk_count} chunks)")
# Delete a document
client.agents.delete_document("abc123", doc.id)Agent docs vs Share docs: Agent documents (agents.upload_document) are shared knowledge for all users. Share documents (shares.upload_document) are per-session personal uploads.
Chat
Basic Chat
response = client.chat("What's the weather?", agent_id="abc123")
print(response.content)Streaming
for chunk in client.chat_stream("Tell me a story", agent_id="abc123"):
if chunk.type == "text":
print(chunk.content, end="", flush=True)Conversation Context
context = []
response = client.chat("My name is Alice", agent_id="abc123")
context.append({"role": "user", "content": "My name is Alice"})
context.append({"role": "assistant", "content": response.content})
response = client.chat("What's my name?", agent_id="abc123", context=context)
print(response.content) # "Alice"Share Links
Share agents with external users via links. Supports authentication, file uploads, and RAG-powered chat.
# Create a share link
share = client.shares.create(
agent_id="abc123",
require_sign_in=True, # Require end-user authentication
allow_file_upload=True, # Allow visitors to upload documents
include_memory=False, # Share agent memory with visitors
max_messages=100, # Message limit (0 = unlimited)
expires_in_days=30, # Link expiration (None = permanent)
)
print(f"Share URL: https://ai-teammate.net{share.share_url}")
# Chat via share link
response = client.shares.chat(share.share_code, "Hello!")
print(response.content)
# Upload a document (triggers RAG indexing)
doc = client.shares.upload_document(share.share_code, "./report.pdf")
print(f"Uploaded: {doc.filename} ({doc.chunk_count} chunks)")
# Chat about the document
response = client.shares.chat(share.share_code, "Summarize the report")
print(response.content)
# List / delete share links
shares = client.shares.list("abc123")
client.shares.delete("abc123", share.id)Full Flow: Create → Share → Upload → RAG Chat
from ai_teammate import AITeammate
client = AITeammate(api_key="at_your_api_key")
# 1. Create an agent
agent = client.agents.create(
name="Customer Support Bot",
system_prompt="You are a friendly customer support agent.",
)
# 2. Create a share link
share = client.shares.create(
agent_id=agent.id,
allow_file_upload=True,
require_sign_in=False,
max_messages=100,
)
print(f"Share URL: https://ai-teammate.net{share.share_url}")
# 3. Upload FAQ document
doc = client.shares.upload_document(share.share_code, "./faq.pdf")
print(f"Indexed: {doc.chunk_count} chunks")
# 4. Chat — agent answers using the uploaded document
response = client.shares.chat(share.share_code, "What is the refund policy?")
print(response.content)End-User Authentication
Share links with require_sign_in=True provide visitor authentication flows.
Email Registration
# 1. Register (sends verification code to email)
result = client.end_users.register(
agent_id="abc123",
name="John",
email="john@example.com",
)
# 2. Verify email with code
result = client.end_users.verify(
agent_id="abc123",
email="john@example.com",
code="123456",
)
# 3. Set password → get auth token
auth = client.end_users.set_password(
agent_id="abc123",
email="john@example.com",
password="secure_password",
)
token = auth.token
# 4. Chat with end-user token
response = client.shares.chat(share_code, "Hello!", end_user_token=token)Login
auth = client.end_users.login(
agent_id="abc123",
email="john@example.com",
password="secure_password",
)
token = auth.tokenGoogle OAuth
# Get Google OAuth URL
result = client.end_users.google_auth_url(
agent_id="abc123",
source="my-app",
return_url="https://myapp.com/callback",
)
print(result["url"]) # Redirect user to this URL
# Exchange code for token (in your callback handler)
auth = client.end_users.google_callback(
agent_id="abc123",
code="google_auth_code",
)
token = auth.token
print(f"New user: {auth.is_new}")Team Chat
Multi-agent conversations with TeamChatResponse.
# Create a team
team = client.teams.create(
name="Dream Team",
chat_mode="brainstorm",
)
# Add agents to team
client.teams.add_agent(team.id, "agent_1")
client.teams.add_agent(team.id, "agent_2")
# Team chat (multi-agent discussion)
response = client.teams.chat(team.id, "Brainstorm startup ideas!")
print(response.summary)
for r in response.responses:
print(f"[{r.agent_name}] {r.content}")| Mode | Description |
|---|---|
round-robin | Sequential responses, referencing prior opinions |
parallel | Independent concurrent responses |
debate | Pro/con discussion |
brainstorm | Idea generation + voting |
expert | Auto-selects optimal agent for the question |
Memories
# Add memory to agent
memory = client.memories.create(
agent_id="abc123",
content="User prefers concise responses",
category="preferences",
)
# List memories
memories = client.memories.list(agent_id="abc123")
# Search memories
results = client.memories.search(agent_id="abc123", query="preferences")API Key Types
| Type | Issued From | Scope |
|---|---|---|
| Global | Settings page | All operations |
| Agent-scoped | Agent settings | Chat, read, memory for that agent |
| Team-scoped | Team settings | Chat, read for that team |
Use scoped keys to grant restricted access to third-party apps.
Async Support
All methods have async equivalents with a prefix. Use context manager for automatic cleanup.
import asyncio
async def main():
async with AITeammate(api_key="at_xxx") as client:
# Async chat
response = await client.achat("Hello!", agent_id="abc123")
# Async streaming
async for chunk in client.achat_stream("Tell me a story", agent_id="abc123"):
print(chunk.content, end="")
asyncio.run(main())Error Handling
from ai_teammate import (
AITeammateError,
AuthenticationError,
RateLimitError,
NotFoundError,
)
try:
response = client.chat("Hello!", agent_id="invalid_id")
except NotFoundError as e:
print(f"Agent not found: {e}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
except AuthenticationError as e:
print(f"Invalid API key: {e}")
except AITeammateError as e:
print(f"Error: {e}")Configuration
client = AITeammate(
api_key="at_xxx",
base_url="https://ai-teammate.net/api", # Custom API URL
timeout=30.0, # Request timeout in seconds
)API Reference
Client Methods
| Method | Description |
|---|---|
chat(message, agent_id) | Chat with an agent |
chat_stream(message, agent_id) | Stream chat response |
achat(message, agent_id) | Async chat |
achat_stream(message, agent_id) | Async stream |
Resources
| Resource | Methods |
|---|---|
| agents | list, get, create, update, delete, upload_document, list_documents, delete_document |
| teams | list, get, create, delete, add_agent, remove_agent, list_agents, chat |
| memories | list, get, create, delete, search |
| shares | create, list, delete, get_info, chat, upload_document, get_history |
| end_users | register, verify, set_password, login, validate, forgot_password, google_auth_url, google_callback |
| bookmarks | save, list, delete, share |
Framework Integration
FastAPI
from fastapi import FastAPI
from ai_teammate import AITeammate
app = FastAPI()
client = AITeammate(api_key="at_xxx")
@app.post("/chat")
async def chat(message: str, agent_id: str):
response = await client.achat(message, agent_id=agent_id)
return {"reply": response.content}Flask
from flask import Flask, request
from ai_teammate import AITeammate
app = Flask(__name__)
client = AITeammate(api_key="at_xxx")
@app.route("/chat", methods=["POST"])
def chat():
data = request.json
response = client.chat(data["message"], agent_id=data["agent_id"])
return {"reply": response.content}REST API (Direct HTTP)
Call the API directly from JavaScript/TypeScript without the Python SDK. All endpoints are under https://ai-teammate.net/api.
Authentication
Include your API Key or JWT Bearer token in the Authorization header.
// API Key method
const headers = { "Authorization": "Bearer at_your_api_key" };
// Or JWT token (obtained after login)
const headers = { "Authorization": "Bearer eyJhbG..." };
const res = await fetch("https://ai-teammate.net/api/agents", { headers });
const agents = await res.json();Agent List
Response includes enabled_skills and avatar_url fields.
const res = await fetch("https://ai-teammate.net/api/agents", {
headers: { "Authorization": "Bearer at_xxx" },
});
const agents = await res.json();
// Each agent object:
// {
// id: "abc-123",
// name: "My Agent",
// avatar_url: "https://api.dicebear.com/7.x/...",
// enabled_skills: ["core", "ext_device_gw", "ext_session_mgr"],
// description: "...",
// ...
// }Chat (Non-streaming)
const res = await fetch("https://ai-teammate.net/api/agents/abc-123/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer at_xxx",
},
body: JSON.stringify({ message: "Hello!" }),
});
const data = await res.json();
console.log(data.content);SSE Streaming Protocol
The /agents/{agent_id}/chat/stream endpoint returns Server-Sent Events (SSE). Each event follows the format: data: {"type":"...", ...}
| type | Fields | Description |
|---|---|---|
| text | content | Text chunk (streaming fragment) |
| tool_start | name, args, side_effect | Tool execution started |
| tool_end | name, status, result, side_effect | Tool execution completed |
| meta | conversation_id | Conversation metadata |
| done | tokens_input, tokens_output | Stream finished |
| error | message | Error occurred |
// Stateful SSE parser (handles partial chunks)
function createSSEParser() {
let buffer = "";
return {
feed(chunk) {
buffer += chunk;
const events = [];
const parts = buffer.split("\n\n");
buffer = parts.pop() || "";
for (const part of parts) {
for (const line of part.split("\n")) {
const trimmed = line.startsWith("data: ") ? line.slice(6) : line;
if (!trimmed) continue;
try {
const parsed = JSON.parse(trimmed);
if (parsed?.type) events.push(parsed);
} catch {}
}
}
return events;
},
};
}
// Usage
const res = await fetch("/api/agents/abc-123/chat/stream", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: "Bearer at_xxx" },
body: JSON.stringify({ message: "Hello!" }),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
const parser = createSSEParser();
let content = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
for (const evt of parser.feed(decoder.decode(value, { stream: true }))) {
if (evt.type === "text") content += evt.content;
else if (evt.type === "tool_start") console.log("Tool:", evt.name);
else if (evt.type === "meta") console.log("ConvID:", evt.conversation_id);
}
}
console.log("Final:", content);OAuth External App Integration
External apps can use AI Teammate accounts for login. No need to register additional Google OAuth callback URIs — use the return_to parameter.
Flow
External app calls GET /api/auth/google?return_to={callback_url}
User completes Google login
Redirects to ai-teammate.net/auth/google/callback (existing callback URI)
If state contains return_to → redirects to {callback_url}?token={jwt}
External app calls GET /api/auth/me with the token to get user info
// 1. Get Google auth URL with return_to
const res = await fetch(
"https://ai-teammate.net/api/auth/google?return_to=" +
encodeURIComponent("https://myapp.com/auth/callback")
);
const { url } = await res.json();
// 2. Redirect user to Google
window.location.href = url;
// 3. In your /auth/callback page, extract the token
const params = new URLSearchParams(window.location.search);
const token = params.get("token");
// 4. Validate token and get user info
const me = await fetch("https://ai-teammate.net/api/auth/me", {
headers: { Authorization: "Bearer " + token },
}).then(r => r.json());
console.log(me.name, me.email, me.avatar_url);Branding API (White-label)
Retrieve branding configuration from DeployedApp by domain or slug. External apps can dynamically apply logo, colors, and app name at runtime. No authentication required.
// Query by domain
const res = await fetch(
"https://ai-teammate.net/api/apps/branding?domain=fleet.mycompany.com"
);
const brand = await res.json();
// {
// name: "My Fleet Control",
// subtitle: "Smart Factory Ops",
// logo: "https://mycompany.com/logo.png",
// accent: "#1428A0",
// bg: "#0d1117",
// agent_id: "abc-123" // null if no match
// }
// Apply to your app
document.title = brand.name;
document.documentElement.style.setProperty("--accent", brand.accent);