# Agents API

Create, manage, and execute AI agents programmatically with the TeamDay Agents API.

# Agents API

Agents are customizable AI assistants that can perform tasks, analyze data, and automate workflows. Use the Agents API to programmatically create and manage agents for your organization.

**Base URL:** `https://cc.teamday.ai/api/v1/agents`

**Authentication:** [Personal Access Token](https://docs.teamday.ai/api/authentication) required

---

## Endpoints Overview

| Method | Endpoint | Description | Status |
|--------|----------|-------------|--------|
| GET | `/agents` | List all agents | ✅ Working |
| POST | `/agents` | Create new agent | ✅ Working |
| GET | `/agents/[id]` | Get agent details | ✅ Working |
| PATCH | `/agents/[id]` | Update agent | ✅ Working |
| DELETE | `/agents/[id]` | Delete agent | ✅ Working |
| POST | `/agents/[id]/execute` | Execute agent | ✅ Working |

**Test Results:** 6/6 endpoints operational

---

## Agent Object

### Properties

```typescript
{
  id: string              // Agent ID (Firestore auto-generated)
  name: string            // Display name
  role: string            // Agent role/purpose
  systemPrompt: string    // System instructions
  visibility: string      // "private" | "organization" | "public" | "unlisted"
  organizationId: string  // Owner organization
  userId: string          // Creator user ID
  createdAt: string       // ISO 8601 timestamp
  updatedAt: string       // ISO 8601 timestamp
  archived?: boolean      // True if soft-deleted
}
```

### Example Object

```json
{
  "id": "abc123def456",
  "name": "Research Assistant",
  "role": "Research and data analysis",
  "systemPrompt": "You are a helpful research assistant specializing in data analysis and summarization.",
  "visibility": "organization",
  "organizationId": "org_xyz789",
  "userId": "user_456",
  "createdAt": "2025-12-09T10:30:00Z",
  "updatedAt": "2025-12-09T10:30:00Z"
}
```

---

## List Agents

Retrieve all agents for your organization.

### Request

```http
GET /api/v1/agents
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
```

**Query Parameters:** None

### Response

**Success (200 OK):**
```json
{
  "success": true,
  "agents": [
    {
      "id": "abc123def456",
      "name": "Research Assistant",
      "role": "Research and analysis",
      "systemPrompt": "You are a helpful research assistant.",
      "visibility": "organization",
      "organizationId": "org_xyz789",
      "userId": "user_456",
      "createdAt": "2025-12-09T10:30:00Z",
      "updatedAt": "2025-12-09T10:30:00Z"
    },
    {
      "id": "def456ghi789",
      "name": "Code Reviewer",
      "role": "Code review and suggestions",
      "systemPrompt": "You are an expert code reviewer.",
      "visibility": "organization",
      "organizationId": "org_xyz789",
      "userId": "user_789",
      "createdAt": "2025-12-08T15:20:00Z",
      "updatedAt": "2025-12-09T09:15:00Z"
    }
  ],
  "total": 2
}
```

**Empty result:**
```json
{
  "success": true,
  "agents": [],
  "total": 0
}
```

**Error (401 Unauthorized):**
```json
{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Unauthorized. Invalid or expired token"
}
```

### Example

```bash
curl https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"
```

---

## Create Agent

Create a new AI agent for your organization.

### Request

```http
POST /api/v1/agents
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
Content-Type: application/json
```

**Body:**
```json
{
  "name": "Research Assistant",
  "role": "Research and data analysis",
  "systemPrompt": "You are a helpful research assistant specializing in data analysis and summarization.",
  "visibility": "organization"
}
```

**Required Fields:**
- `name` (string) - Agent display name
- `systemPrompt` (string) - System instructions for the agent

**Optional Fields:**
- `role` (string) - Agent role description (default: `"Assistant"`)
- `visibility` (string) - Access level: `"private"`, `"organization"`, `"public"`, or `"unlisted"` (default: `"organization"`)

### Response

**Success (200 OK):**
```json
{
  "success": true,
  "id": "abc123def456",
  "name": "Research Assistant",
  "status": "active",
  "chatUrl": "/org/spaces/spaceId/chats/chatId"
}
```

**Error (400 Bad Request):**
```json
{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Missing required field: name"
}
```

**Error (401 Unauthorized):**
```json
{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Unauthorized. Invalid or expired token"
}
```

### Example

```bash
curl -X POST https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Research Assistant",
    "role": "Research and data analysis",
    "systemPrompt": "You are a helpful research assistant specializing in data analysis and summarization.",
    "visibility": "organization"
  }'
```

---

## Get Agent

Retrieve details for a specific agent by ID.

### Request

```http
GET /api/v1/agents/[id]
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
```

**Path Parameters:**
- `id` (string) - Agent ID (Firestore auto-generated)

### Response

**Success (200 OK):**
```json
{
  "success": true,
  "agent": {
    "id": "abc123def456",
    "name": "Research Assistant",
    "role": "Research and data analysis",
    "systemPrompt": "You are a helpful research assistant specializing in data analysis and summarization.",
    "visibility": "organization",
    "organizationId": "org_xyz789",
    "userId": "user_456",
    "createdAt": "2025-12-09T10:30:00Z",
    "updatedAt": "2025-12-09T10:30:00Z"
  }
}
```

**Error (404 Not Found):**
```json
{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Agent not found"
}
```

**Error (401 Unauthorized):**
```json
{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Unauthorized. Invalid or expired token"
}
```

### Example

```bash
curl https://cc.teamday.ai/api/v1/agents/abc123def456 \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"
```

---

## Update Agent

Update an existing agent's properties.

### Request

```http
PATCH /api/v1/agents/[id]
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
Content-Type: application/json
```

**Path Parameters:**
- `id` (string) - Agent ID (Firestore auto-generated)

**Body (all fields optional):**
```json
{
  "name": "Updated Research Assistant",
  "role": "Advanced research and analysis",
  "systemPrompt": "You are an expert research assistant with deep knowledge of data analysis.",
  "visibility": "organization"
}
```

**Updatable Fields:**
- `name` (string) - Agent display name
- `role` (string) - Agent role description
- `systemPrompt` (string) - System instructions
- `visibility` (string) - Access level: `"private"`, `"organization"`, `"public"`, or `"unlisted"`

**Note:** Only include fields you want to update. Omitted fields remain unchanged.

### Response

**Success (200 OK):**
```json
{
  "success": true,
  "message": "Agent updated successfully"
}
```

**Error (404 Not Found):**
```json
{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Agent not found"
}
```

**Error (400 Bad Request):**
```json
{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Invalid visibility value. Must be: private, organization, public, or unlisted"
}
```

### Example

```bash
curl -X PATCH https://cc.teamday.ai/api/v1/agents/abc123def456 \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Research Assistant",
    "visibility": "organization"
  }'
```

---

## Delete Agent

Soft delete an agent. The agent is marked as deleted but not permanently removed from the database.

### Request

```http
DELETE /api/v1/agents/[id]
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
```

**Path Parameters:**
- `id` (string) - Agent ID (Firestore auto-generated)

### Response

**Success (200 OK):**
```json
{
  "success": true,
  "message": "Agent deleted successfully"
}
```

**Error (404 Not Found):**
```json
{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Agent not found"
}
```

**Error (401 Unauthorized):**
```json
{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Unauthorized. Invalid or expired token"
}
```

### Example

```bash
curl -X DELETE https://cc.teamday.ai/api/v1/agents/abc123def456 \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"
```

### Notes

**Soft Delete Behavior:**
- Agent is marked as archived (`archived: true`)
- Agent no longer appears in list results
- Agent cannot be retrieved or updated
- Execution history preserved
- **Cannot be undeleted via API** (contact support to restore)

**Alternative to deletion:**
- Consider updating `visibility` to `"private"` to hide from organization

---

## Execute Agent

Execute an agent with a message and receive a response.

### Request

```http
POST /api/v1/agents/[id]/execute
```

**Headers:**
```http
Authorization: Bearer td_xxxxx...
Content-Type: application/json
```

**Path Parameters:**
- `id` (string) - Agent ID (Firestore auto-generated)

**Body:**
```json
{
  "message": "Analyze this data and provide insights",
  "spaceId": "space_abc123",
  "sessionId": "session_abc123",
  "chatId": "chat_abc123",
  "stream": false
}
```

**Fields:**
- `message` (string, required) - User message to send to agent
- `spaceId` (string, optional) - Space/workspace to execute in
- `sessionId` (string, optional) - Existing session to continue
- `chatId` (string, optional) - Existing chat to continue
- `stream` (boolean, optional) - Enable streaming response (default: `false`)

### Response

**Non-streaming response (200 OK):**
```json
{
  "success": true,
  "executionId": "exec-1234567890-abc",
  "chatId": "chat_abc123",
  "sessionId": "session_abc123",
  "result": "Based on my analysis of the data..."
}
```

**Streaming response (`stream: true`):**

When `stream` is `true`, the response is an SSE stream (content-type: `text/event-stream`). The stream starts with a `meta` event containing IDs, followed by `message` events with content, and ends with a `result` event:

```text
event: meta
data: {"executionId":"exec-1234567890-abc","chatId":"chat_abc123","sessionId":"session_abc123"}

event: message
data: {"messageType":"stream_event","delta":{"type":"text_delta","text":"Based"}}

event: message
data: {"messageType":"stream_event","delta":{"type":"text_delta","text":" on my analysis..."}}

event: result
data: {"sessionId":"session_abc123","usage":{"input_tokens":856,"output_tokens":378}}
```

**SSE event types:**
- `meta` — Initial metadata (executionId, chatId, sessionId). Sent first.
- `message` — Content events. `messageType: "stream_event"` contains text deltas. `messageType: "assistant"` contains complete content blocks.
- `result` — Final event with sessionId (for multi-turn) and token usage.
- `error` — Error event with `{ message }` payload.

### Examples

**Non-streaming:**
```bash
curl -X POST https://cc.teamday.ai/api/v1/agents/abc123def456/execute \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Analyze this data and provide insights",
    "stream": false
  }'
```

**Streaming:**
```bash
curl -N -X POST https://cc.teamday.ai/api/v1/agents/abc123def456/execute \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "message": "Analyze this data and provide insights",
    "stream": true
  }'
```

**Multi-turn (continue session):**
```bash
curl -X POST https://cc.teamday.ai/api/v1/agents/abc123def456/execute \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Now break it down by region",
    "sessionId": "session_abc123",
    "chatId": "chat_abc123",
    "spaceId": "space_xyz",
    "stream": true
  }'
```

---

## Visibility Levels

Agents support four visibility levels that control who can see and use them:

### Private

**Level:** `"private"`

**Access:**
- Visible only to the creator
- Only creator can execute
- Not visible in organization's agent list

**Use cases:**
- Personal assistants
- Experimental agents
- Sensitive workflows

### Organization

**Level:** `"organization"`

**Access:**
- Visible to all organization members
- All members can execute
- Appears in organization's shared agents

**Use cases:**
- Team collaboration
- Shared knowledge bases
- Company-wide tools

### Public

**Level:** `"public"`

**Access:**
- Visible to all authenticated users
- Anyone can execute
- Listed in public agent listings

**Use cases:**
- Community-shared agents
- Open-source tools
- Public demos

### Unlisted

**Level:** `"unlisted"`

**Access:**
- Not shown in agent listings or search
- Accessible only via direct link/ID
- Only the owner can see it in their dashboard

**Use cases:**
- Shared with specific people via link
- Beta testing agents
- Agents embedded in external tools

---

## Best Practices

### Agent Design

**System Prompts:**
- Be specific about the agent's role and capabilities
- Include examples of desired behavior
- Set clear boundaries on what the agent should/shouldn't do
- Keep prompts under 2000 characters for optimal performance

**Example:**
```json
{
  "systemPrompt": "You are a code review assistant specializing in Python. Focus on:\n1. Code quality and readability\n2. Performance optimizations\n3. Security vulnerabilities\n4. Best practices\n\nProvide constructive feedback with specific examples."
}
```

### Naming Conventions

**Agent Names:**
- Use descriptive, action-oriented names
- Include the agent's specialty or domain
- Keep under 50 characters

**Good examples:**
- "Python Code Reviewer"
- "Customer Support Assistant"
- "Data Analysis Agent"

**Avoid:**
- Generic names like "Agent 1", "My Agent"
- Very long names that truncate in UI

### Security

**Visibility:**
- Default visibility is `"organization"` for new agents
- Use `"private"` for sensitive or experimental agents
- Review system prompts before making agents public

**Sensitive Data:**
- Don't include API keys or credentials in system prompts
- Use TeamDay's [secrets management instead
- Agents inherit user permissions - scope tokens appropriately

### Performance

**Agent Updates:**
- Changes to `systemPrompt` take effect immediately on next execution
- No need to recreate agent to update behavior
- Consider versioning by including version in agent name (e.g., "Research Assistant v2")

**Rate Limiting:**
- While no formal limits exist, avoid creating 100+ agents
- Reuse agents with different messages rather than creating duplicates
- Delete unused agents to keep organization clean

---

## Common Patterns

### Multi-Purpose Agent

Create one agent that handles multiple related tasks:

```bash
curl -X POST https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Assistant",
    "role": "Code review, documentation, and debugging",
    "systemPrompt": "You are an engineering assistant. Depending on the task:\n- Code review: Focus on quality, security, performance\n- Documentation: Write clear, concise docs with examples\n- Debugging: Analyze errors and suggest fixes\n\nAdapt your response to the user'\''s specific request.",
    "visibility": "organization"
  }'
```

### Specialized Agent

Create focused agents for specific domains:

```bash
curl -X POST https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SQL Query Optimizer",
    "role": "SQL optimization and tuning",
    "systemPrompt": "You are an expert SQL optimizer. Analyze queries for:\n- Index usage\n- Join efficiency\n- Query plan optimization\n- Best practices for the target database (PostgreSQL, MySQL, etc.)\n\nProvide specific, actionable recommendations.",
    "visibility": "private"
  }'
```

### Team Collaboration

Share agents across your organization:

```bash
# Create shared agent
curl -X POST https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Team Standup Helper",
    "role": "Daily standup organization",
    "systemPrompt": "Help teams organize daily standups. Format updates in a clear, concise way:\n- What was accomplished yesterday\n- Plans for today\n- Any blockers\n\nKeep responses brief and actionable.",
    "visibility": "organization"
  }'
```

---

## Error Handling

### Common Errors

**400 Bad Request:**
- Missing required fields (`name`, `systemPrompt`)
- Invalid `visibility` value
- Malformed JSON

**401 Unauthorized:**
- Missing `Authorization` header
- Invalid or expired token
- Token lacks required permissions

**404 Not Found:**
- Agent ID doesn't exist
- Agent was deleted
- Wrong organization (agent belongs to different org)

**500 Internal Server Error:**
- Database connectivity issues
- Service temporarily unavailable
- Contact support if persistent

### Error Response Format

All errors follow this structure:

```json
{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Detailed error description"
}
```

### Retry Strategy

**Recommended approach:**

```javascript
async function createAgentWithRetry(agentData, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.TEAMDAY_TOKEN}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(agentData)
      })

      if (!response.ok) {
        const error = await response.json()

        // Don't retry client errors (4xx)
        if (response.status >= 400 && response.status < 500) {
          throw new Error(error.message)
        }

        // Retry server errors (5xx)
        if (i === maxRetries - 1) throw new Error(error.message)

        // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000))
        continue
      }

      return await response.json()

    } catch (err) {
      if (i === maxRetries - 1) throw err
    }
  }
}
```

---

## Related Resources

- [Authentication](https://docs.teamday.ai/api/authentication) - PAT token setup and security
- [Executions API](https://docs.teamday.ai/api/executions) - Track agent execution history
- [Tasks API](https://docs.teamday.ai/api/tasks) - Manage agent tasks and workflows
- [Error Reference](https://docs.teamday.ai/api/errors) - Complete error code documentation

---

## Need Help?

**Issues with agents?**
- Check [error reference](https://docs.teamday.ai/api/errors) for troubleshooting
- Verify token has correct permissions
- Test with simple agent first

**Questions?**
- 📧 Email: support at teamday.ai
- 💬 Discord: [Join community](https://discord.gg/teamday)
- 🐛 Report bugs: [GitHub Issues](https://github.com/TeamDay-AI/teamday/issues)

---

**Last Updated:** February 24, 2026
