> For the complete documentation index, see [llms.txt](https://docs.graphlit.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.graphlit.dev/api-guides/use-cases/feeds/messaging/feed-create-slack.md).

# Create Slack Feed

## User Intent

"I want to sync Slack channels into Graphlit for search and AI interactions"

## Operation

* **SDK Method**: `graphlit.createFeed()` with Slack configuration
* **GraphQL**: `createFeed` mutation
* **Entity Type**: Feed
* **Common Use Cases**: Slack channel sync, team communication search, chat history RAG

## TypeScript (Canonical)

```typescript
import { Graphlit } from 'graphlit-client';
import {
  ContentTypes,
  FeedInput,
  FeedListingTypes,
  FeedTypes,
  SearchTypes,
} from 'graphlit-client/dist/generated/graphql-types';

const graphlit = new Graphlit();

// Optional: Query available Slack channels (requires token/OAuth)
const channelsResponse = await graphlit.querySlackChannels({
  token: process.env.SLACK_TOKEN!,
});

console.log('Available channels:', channelsResponse.slackChannels?.results);

// Step 1: Create a Slack feed for ONE channel (one feed per channel)
const feedInput: FeedInput = {
  name: 'Engineering Slack',
  type: FeedTypes.Slack,
  slack: {
    type: FeedListingTypes.Past,
    channel: 'engineering',
    token: process.env.SLACK_TOKEN!,
    readLimit: 100,
    includeAttachments: true,
  },
};

const response = await graphlit.createFeed(feedInput);
const feedId = response.createFeed.id;

console.log(`Slack feed created: ${feedId}`);

// Step 3: Poll for feed completion
while (true) {
  const status = await graphlit.isFeedDone(feedId);
  if (status.isFeedDone.result) {
    break;
  }
  console.log('Still syncing Slack messages...');
  await new Promise((resolve) => setTimeout(resolve, 10_000));
}

console.log('Slack feed sync complete!');
```

## Parameters

### FeedInput (Required)

* **`name`** (string): Display name for the feed
* **`type`** (FeedTypes): Must be `SLACK`
* **`slack`** (SlackFeedPropertiesInput): Slack-specific configuration

### SlackFeedPropertiesInput (Required)

* **`type`** (FeedListingTypes): `Past` (backfill then continue) or `New` (new items only)
* **`channel`** (string): Slack channel name (one channel per feed)
* **`token`** (string): Slack token (Token auth) or use `connector` (Connector auth)
* **`includeAttachments`** (boolean, optional): include file attachments
* **`readLimit`** (int, optional): items per poll/run

### Optional

* **`correlationId`** (string): For tracking in production
* **`collections`** (EntityReferenceInput\[]): Auto-add synced messages to collections
* **`workflow`** (EntityReferenceInput): Apply workflow to messages

## Response

```typescript
{
  createFeed: {
    id: string;              // Feed ID
    name: string;            // Feed name
    state: EntityState;      // ENABLED
    type: FeedTypes.Slack;   // SLACK
    slack: {
      channel: string;
      includeAttachments?: boolean;
      type?: FeedListingTypes;
    }
  }
}
```

## Developer Hints

### OAuth Token Requirements

**Slack OAuth Scopes Needed**:

* `channels:read` - List public channels
* `channels:history` - Read public channel messages
* `groups:read` - List private channels (if needed)
* `groups:history` - Read private channel messages (if needed)
* `users:read` - Get user information

**Getting a Slack Token**:

1. Create Slack App at <https://api.slack.com/apps>
2. Add OAuth scopes under "OAuth & Permissions"
3. Install app to workspace
4. Copy Bot User OAuth Token (starts with `xoxb-`)

### Feed is Continuous Sync

```typescript
// Feed continuously monitors for new messages
const feed = await graphlit.createFeed(feedInput);

// New messages appear automatically as content
// No need to manually trigger sync
```

**Important**: Feeds run continuously. To stop syncing, disable or delete the feed.

### Polling for Initial Sync

```typescript
// After creating feed, wait for initial sync
const feedId = response.createFeed.id;

let isDone = false;
while (!isDone) {
  const status = await graphlit.isFeedDone(feedId);
  isDone = status.isFeedDone.result || false;
  
  if (!isDone) {
    await new Promise(resolve => setTimeout(resolve, 10000));
  }
}

// Now query synced messages
const messages = await graphlit.queryContents({
  feeds: [{ id: feedId }],
  types: [ContentTypes.Message]
});

console.log(`Synced ${messages.contents.results.length} messages`);
```

### Channel Discovery

```typescript
// List all channels user has access to
const channels = await graphlit.querySlackChannels({ token: slackToken });
const channelNames = channels.slackChannels?.results ?? [];

// One feed per channel (recommended if you want multiple channels)
for (const channel of channelNames.filter((c) => c.startsWith('eng-') || c.startsWith('dev-'))) {
  await graphlit.createFeed({
    name: `Slack #${channel}`,
    type: FeedTypes.Slack,
    slack: {
      type: FeedListingTypes.Past,
      channel,
      token: slackToken,
    },
  });
}
```

## Variations

### 1. Sync Specific Channels Only

Create multiple feeds (one per channel):

```typescript
await graphlit.createFeed({
  name: 'Slack #customer-support',
  type: FeedTypes.Slack,
  slack: {
    type: FeedListingTypes.Past,
    channel: 'customer-support',
    token: slackToken,
  },
});
```

### 2. Sync with Auto-Collection

Automatically add messages to a collection:

```typescript
// Create collection first
const collectionResponse = await graphlit.createCollection({
  name: 'Slack Messages'
});

// Create feed with collection
const feedInput: FeedInput = {
  name: 'Team Slack',
  type: FeedTypes.Slack,
  slack: {
    type: FeedListingTypes.Past,
    token: slackToken
  },
  collections: [{ id: collectionResponse.createCollection.id }]
};
```

### 3. Sync with Entity Extraction

Extract people and topics from messages:

```typescript
// Create workflow for entity extraction
const workflowResponse = await graphlit.createWorkflow({
  name: 'Extract Slack Entities',
  extraction: {
    jobs: [{
      connector: {
        type: EntityExtractionServiceTypes.ModelText,
        modelText: {
          extractedTypes: [
            ObservableTypes.Person,
            ObservableTypes.Organization,
            ObservableTypes.Label
          ]
        }
      }
    }]
  }
});

// Create feed with workflow
const feedInput: FeedInput = {
  name: 'Slack with Extraction',
  type: FeedTypes.Slack,
  slack: {
    type: FeedListingTypes.Past,
    token: slackToken
  },
  workflow: { id: workflowResponse.createWorkflow.id }
};
```

### 4. Query Synced Messages

Search through synced Slack messages:

```typescript
// After feed sync completes
const results = await graphlit.queryContents({
  feeds: [{ id: feedId }],
  types: [ContentTypes.Message],
  search: 'deployment issues',
  searchType: SearchTypes.Hybrid
});

results.contents.results.forEach(msg => {
  console.log(`${msg.name}: ${msg.summary}`);
});
```

### 5. Multi-Channel Pattern with Filtering

Sync multiple channels and filter by date:

```typescript
const feedInput: FeedInput = {
  name: 'Recent Engineering Discussions',
  type: FeedTypes.Slack,
  slack: {
    type: FeedListingTypes.Past,
    channel: 'engineering',
    token: slackToken
  }
};

const response = await graphlit.createFeed(feedInput);

// Wait for sync
await waitForFeedCompletion(response.createFeed.id);

// Query only recent messages
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);

const recentMessages = await graphlit.queryContents({
  feeds: [{ id: response.createFeed.id }],
  creationDateRange: {
    from: lastWeek,
    to: new Date()
  }
});
```

## Common Issues

**Issue**: `Invalid token` error\
**Solution**: Ensure Slack token has required OAuth scopes. Regenerate token with correct scopes.

**Issue**: `Channel not found`\
**Solution**: Use `querySlackChannels()` to confirm the exact channel name. The app/user must have access to the channel.

**Issue**: Feed created but no messages syncing\
**Solution**: Verify token has `channels:history` scope and the app/user has access to the channel.

**Issue**: Feed sync taking too long\
**Solution**: This is normal for channels with many messages. Use `isFeedDone()` to poll. Initial sync can take minutes for large channels.

## Production Example
