SDKs and Client Libraries
Official SDKs and client libraries for integrating with the TeamDay platform.
Overview
TeamDay provides client libraries for building applications on top of the platform. All SDKs use Firebase as the underlying transport layer with Firestore for real-time data and Firebase Auth for authentication.
| SDK | Status | Language | Use Case |
|---|---|---|---|
| JavaScript/TypeScript SDK | ✅ Production | TypeScript | Web apps (Nuxt/Vue) |
| REST API | 🚧 Planned | N/A | Server-side integrations |
| Python SDK | 📋 Roadmap | Python | Scripts, automation |
| CLI Tool | ✅ Production | TypeScript | Development workflow |
JavaScript/TypeScript SDK
The primary SDK is built with Vue 3 composables and works seamlessly with Nuxt 3 applications.
Installation
# Using bun (recommended)
bun add firebase firebase/firestore
# Using npm
npm install firebase
Configuration
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
firebase: {
apiKey: process.env.NUXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NUXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NUXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NUXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NUXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NUXT_PUBLIC_FIREBASE_APP_ID,
}
}
}
})
Core Composables
Authentication - useAuth()
Manages user authentication and session state.
const {
user, // Current user (reactive)
loading, // Auth state loading
signInWithGoogle,
signInWithGitHub,
signOut
} = useAuth()
// Check if user is authenticated
if (user.value) {
console.log('User ID:', user.value.uid)
console.log('Email:', user.value.email)
}
// Sign in with Google
await signInWithGoogle()
// Sign out
await signOut()
Available Methods:
signInWithGoogle()- OAuth with GooglesignInWithGitHub()- OAuth with GitHubsignInWithEmail(email, password)- Email/password authsignOut()- Sign out current user
Organizations - useOrganizations()
Manage organizations and team memberships.
const {
organizations, // Array of user's organizations
loading,
error,
fetchUserOrganizations,
getOrganization,
createOrganization,
updateOrganization
} = useOrganizations()
// Fetch user's organizations
await fetchUserOrganizations()
// Get specific organization
const org = await getOrganization('org_id')
// Create new organization
const newOrg = await createOrganization('Acme Corp')
// Update organization
await updateOrganization('org_id', {
name: 'Acme Corporation',
logoUrl: 'https://...'
})
Organization Type:
interface Organization {
id: string
name: string
logoUrl?: string
ownerId: string
members: string[]
subscription?: {
tier: 'free' | 'pro' | 'enterprise'
status: 'active' | 'cancelled' | 'expired'
}
createdAt: Date
updatedAt: Date
}
Spaces - useSpaces()
Manage workspaces where agents operate.
const {
spaces, // Array of spaces (reactive, real-time)
chats, // Chats in current space
loading,
error,
fetchSpaces,
createSpace,
updateSpace,
deleteSpace,
initializeSpace
} = useSpaces()
// Subscribe to real-time updates
fetchSpaces('org_id')
// Create a new space
const space = await createSpace(
'org_id',
'Marketing Workspace',
'Space for marketing team',
'organization', // visibility
'https://cover-image.jpg'
)
// Update space
await updateSpace('space_id', {
name: 'Updated Name',
description: 'Updated description'
})
// Initialize workspace (creates file system)
await initializeSpace('space_id', {
type: 'empty' // or 'git', 'readme', 'starterKit'
})
// Soft delete (can be restored)
await softDeleteSpace('space_id')
// Restore deleted space
await restoreSpace('space_id')
// Permanent delete
await deleteSpace('space_id')
Space Type:
interface Space {
id: string
organizationId: string
name: string
description: string
visibility: 'private' | 'organization' | 'public'
ownerId: string
assignedAgents?: string[] // Character IDs
skillIds?: string[] // Skill IDs
pluginIds?: string[] // Plugin IDs
chatCount?: number
fileCount?: number
createdAt: Date
updatedAt: Date
}
Characters (Agents) - useCharacters()
Manage AI agents/assistants.
const {
characters, // Array of characters (reactive, real-time)
loading,
error,
fetchCharacters,
createCharacter,
getCharacter,
updateCharacter,
deleteCharacter
} = useCharacters()
// Subscribe to real-time updates
fetchCharacters('org_id')
// Create a new agent
const agent = await createCharacter(
'org_id',
'Marketing Maven',
'Marketing Assistant',
'You are an expert marketing assistant...',
'organization' // visibility
)
// Get specific character
const character = await getCharacter('char_id')
// Update character
await updateCharacter('char_id', {
name: 'Updated Name',
systemPrompt: 'Updated prompt...',
skillIds: ['research-assistant', 'technical-writer'],
advanced_tools: ['mcp_google_analytics']
})
// Soft delete
await softDeleteCharacter('char_id')
// Restore
await restoreCharacter('char_id')
// Archive (soft delete alternative)
await deleteCharacter('char_id')
Character Type:
interface Character {
id: string
name: string
role: string
initialGreeting: string
system_message: string
image: string
color: string
model?: string
visibility: 'private' | 'organization' | 'public' | 'unlisted'
ownerId: string
organizationId?: string
skillIds?: string[]
advanced_tools?: string[]
tags?: string[]
archived?: boolean
createdAt: Date
}
Chats - useChatCrud()
Manage conversations with agents.
const {
chats, // Array of chats (reactive, real-time)
loading,
error,
fetchChats,
createChat,
getChat,
updateChat,
deleteChat,
toggleChatClosed
} = useChatCrud()
// Fetch chats for a space
await fetchChats('org_id', 'space_id')
// Create new chat
const chat = await createChat('org_id', 'space_id', 'New Conversation')
// Get specific chat
const chat = await getChat('chat_id')
// Update chat
await updateChat('chat_id', {
title: 'Updated Title',
status: 'done'
})
// Toggle closed state
await toggleChatClosed('chat_id')
// Delete chat
await deleteChat('chat_id')
Chat Type:
interface Chat {
id: string
organizationId: string
spaceId: string
title: string
subtitle?: string
status: 'standby' | 'working' | 'done' | 'needs_attention' | 'error'
ownerId: string
lastMessage?: string
sessionId?: string
closed: boolean
closedAt?: Date | null
createdAt: Date
updatedAt: Date
}
Skills - useSkills()
Manage reusable prompt packages.
const {
skills, // Array of skills
loading,
error,
fetchSkills,
createSkill,
updateSkill,
deleteSkill
} = useSkills()
// Fetch skills for organization
await fetchSkills('org_id')
// Create a skill
const skill = await createSkill({
name: 'custom-researcher',
displayName: 'Custom Researcher',
description: 'Custom research skill',
prompt: '# Research Skill\n\nInstructions...',
category: 'research',
builtInTools: ['WebSearch', 'Read'],
visibility: 'organization',
organizationId: 'org_id',
ownerId: 'user_id'
})
// Update skill
await updateSkill('skill_id', {
displayName: 'Updated Name',
prompt: 'Updated instructions...'
})
// Delete skill
await deleteSkill('skill_id')
Skill Type:
interface Skill {
id: string
name: string // kebab-case
displayName: string
description: string
prompt: string // Markdown instructions
category: 'research' | 'writing' | 'data' | 'code' | 'marketing' | 'productivity' | 'file-handling' | 'other'
builtInTools?: string[]
requiredMCPs?: string[]
visibility: 'private' | 'organization' | 'public'
organizationId: string
ownerId: string
version: number
createdAt: Date
}
Missions - useMissions()
Manage long-running autonomous tasks.
const {
missions, // Array of missions
loading,
error,
fetchMissions,
createMission,
updateMission,
pauseMission,
resumeMission
} = useMissions()
// Fetch missions
await fetchMissions('org_id')
// Create mission
const mission = await createMission({
title: 'Daily Report',
goal: 'Generate daily analytics report',
agentType: 'claude',
schedule: {
type: 'cron',
value: '0 9 * * *' // Every day at 9 AM
},
organizationId: 'org_id',
userId: 'user_id'
})
// Update mission
await updateMission('mission_id', {
status: 'paused'
})
// Pause/Resume
await pauseMission('mission_id')
await resumeMission('mission_id')
Real-Time Subscriptions
All data composables provide real-time updates using Firestore's onSnapshot.
Subscription Lifecycle
const { fetchSpaces, unsubscribeSpaces } = useSpaces()
// Start subscription
fetchSpaces('org_id')
// Data updates automatically when Firestore changes
watch(spaces, (newSpaces) => {
console.log('Spaces updated:', newSpaces.length)
})
// Cleanup on unmount
onUnmounted(() => {
unsubscribeSpaces()
})
Auto-Cleanup
Composables handle cleanup automatically in most cases:
// This automatically cleans up on component unmount
const { spaces } = useSpaces()
fetchSpaces('org_id')
Error Handling
All composables follow a consistent error pattern:
const { error, loading } = useSpaces()
// Check loading state
if (loading.value) {
console.log('Loading...')
}
// Check for errors
if (error.value) {
console.error('Error:', error.value)
}
// Try-catch for explicit operations
try {
await createSpace(...)
} catch (err) {
console.error('Failed to create space:', err)
}
TypeScript Support
All types are fully typed with TypeScript:
import type { Space, Character, Skill, Chat } from '~/types'
const space: Space = await getSpace('space_id')
const character: Character = await getCharacter('char_id')
Type Exports:
// From ~/types/space
export type { Space, Chat, ChatMessage, SpaceVisibility }
// From ~/types/character
export type { Character, CharacterVisibility }
// From ~/types/skill
export type { Skill, SkillCategory, SkillVisibility }
// From ~/types/mission
export type { Mission, MissionStatus, AgentType }
// From ~/types/task
export type { Task, TaskStatus, TaskPriority }
// From ~/types/execution
export type { Execution, ExecutionStatus }
Server API Endpoints
TeamDay provides server-side API endpoints for operations requiring elevated permissions.
Base URL
Production: https://teamday.ai/api
Development: http://localhost:3000/api
Authentication
Use Firebase ID tokens for authentication:
const idToken = await user.value?.getIdToken()
const response = await fetch('/api/endpoint', {
method: 'POST',
headers: {
'Authorization': `Bearer ${idToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
Available Endpoints
Space Initialization
POST /api/spaces/:spaceId/init
Content-Type: application/json
{
"type": "empty", // or "git", "readme", "starterKit"
"orgId": "org_id",
"spaceName": "Workspace Name"
}
Space Environment Variables
POST /api/spaces/:spaceId/environment
Content-Type: application/json
{
"environmentVariables": {
"API_KEY": "encrypted_value",
"DATABASE_URL": "encrypted_value"
}
}
Agent Execution
POST /api/agent/execute
Content-Type: application/json
{
"characterId": "char_id",
"spaceId": "space_id",
"message": "User message",
"sessionId": "session_id"
}
Usage Analytics
GET /api/usage/organization/:orgId?period=daily&start=2024-01-01&end=2024-01-31
Authorization: Bearer <id_token>
CLI Tool
The TeamDay CLI provides development workflow commands.
Installation
# Using bun
bun add -g @teamday/cli
# Using npm
npm install -g @teamday/cli
Authentication
# Login via browser OAuth
teamday login
# Verify authentication
teamday whoami
Commands
# Initialize a new space
teamday space init
# Deploy an agent
teamday agent deploy ./agent-config.json
# Run a mission locally
teamday mission run mission_id
# Tail agent logs
teamday logs --follow --space space_id
# Manage environment variables
teamday env set API_KEY=value
teamday env list
Configuration
Create .teamdayrc.json in your project:
{
"organizationId": "org_abc123",
"defaultSpace": "space_456",
"region": "us-central1"
}
Best Practices
1. Always Clean Up Subscriptions
const unsubscribe = ref<Unsubscribe | null>(null)
const subscribe = () => {
if (unsubscribe.value) {
unsubscribe.value()
}
unsubscribe.value = onSnapshot(query, callback)
}
onUnmounted(() => {
if (unsubscribe.value) {
unsubscribe.value()
}
})
2. Handle Undefined Values
Firestore doesn't allow undefined. Always use null or omit:
// ❌ Bad
await updateDoc(docRef, {
optional: undefined
})
// ✅ Good
const cleanData = Object.fromEntries(
Object.entries(data).filter(([_, v]) => v !== undefined)
)
await updateDoc(docRef, cleanData)
3. Use Server Timestamps
import { serverTimestamp } from 'firebase/firestore'
await updateDoc(docRef, {
updatedAt: serverTimestamp()
})
4. Optimistic Updates
For better UX, show changes immediately:
// Add optimistically
optimisticSpaces.value.push(newSpace)
// Then persist
await addDoc(collection, spaceData)
// Snapshot updates with real data
5. Error Boundaries
Wrap operations in try-catch:
try {
await createSpace(...)
} catch (error) {
console.error('Operation failed:', error)
// Show user-friendly error message
toast.error('Failed to create space')
}
Migration from v1 to v2
Breaking Changes
Authentication:
- Changed from custom JWT to Firebase Auth
- Update: Replace
useAuthToken()withuseAuth()
Composables:
- Renamed
useAgents()touseCharacters() - Removed
skillsinline field, useskillIdsinstead
Types:
Agentrenamed toCharactersystemPromptfield renamed tosystem_message
Migration Guide
// v1
const { agents } = useAgents()
// v2
const { characters } = useCharacters()
// v1
const agent = {
systemPrompt: 'You are...',
skills: [{ name: 'research', instructions: '...' }]
}
// v2
const character = {
system_message: 'You are...',
skillIds: ['research-assistant']
}
Version Compatibility
| TeamDay Version | SDK Version | Firebase SDK | Nuxt Version |
|---|---|---|---|
| 1.0.x | 1.0.x | ^10.7.0 | ^3.9.0 |
| 2.0.x | 2.0.x | ^10.12.0 | ^3.13.0 |
Examples
Complete Workspace Setup
<script setup lang="ts">
const { user } = useAuth()
const { organizations, fetchUserOrganizations } = useOrganizations()
const { createSpace, fetchSpaces, spaces } = useSpaces()
const { createCharacter, fetchCharacters } = useCharacters()
// On mount, fetch user's organizations
onMounted(async () => {
await fetchUserOrganizations()
if (organizations.value.length > 0) {
const orgId = organizations.value[0].id
// Subscribe to spaces and characters
fetchSpaces(orgId)
fetchCharacters(orgId)
}
})
// Create a complete workspace
const setupWorkspace = async () => {
const orgId = organizations.value[0].id
// 1. Create space
const space = await createSpace(
orgId,
'My Workspace',
'A workspace for my team',
'organization'
)
// 2. Create agent
const agent = await createCharacter(
orgId,
'Research Assistant',
'Researcher',
'You are an expert researcher...',
'organization'
)
// 3. Assign agent to space
if (space && agent) {
await updateSpace(space.id, {
assignedAgents: [agent.id]
})
}
console.log('Workspace ready!')
}
</script>
Real-Time Chat
<script setup lang="ts">
const { chats, fetchChats } = useChatCrud()
const route = useRoute()
const spaceId = route.params.spaceId as string
const orgId = route.params.orgId as string
// Subscribe to chats in this space
fetchChats(orgId, spaceId)
// Watch for new messages
watch(chats, (newChats) => {
const latestChat = newChats[0]
if (latestChat?.status === 'done') {
console.log('Agent finished:', latestChat.lastMessage)
}
})
</script>
Support
- Documentation: https://teamday.ai/docs
- API Reference: https://teamday.ai/docs/reference
- GitHub: https://github.com/teamday/teamday
- Discord: https://discord.gg/teamday
Roadmap
Q1 2025
- ✅ JavaScript/TypeScript SDK
- ✅ CLI Tool
- 🚧 REST API (beta)
Q2 2025
- 📋 Python SDK
- 📋 Webhook subscriptions
- 📋 GraphQL API
Q3 2025
- 📋 Go SDK
- 📋 Mobile SDKs (React Native)
- 📋 Streaming API for real-time agent output
Contributing
We welcome contributions! See our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/teamday/teamday.git
cd teamday
# Install dependencies
bun install
# Start development server
bun run dev
# Run tests
bun test
License
The TeamDay SDK is released under the MIT License. See LICENSE for details.