# Ingest Event

## Content: Ingest Event

### User Intent

"I want to ingest time-series events or episodic memories into Graphlit for temporal search and recall"

### Operation

* **SDK Method**: `graphlit.ingestEvent()`
* **GraphQL**: `ingestEvent` mutation
* **Entity Type**: Content (Event subtype)
* **Common Use Cases**: User activity logs, calendar events, app events, journal entries, timeline data, audit logs

### TypeScript (Canonical)

```typescript
import { Graphlit } from 'graphlit-client';
import { ContentState, ObservableTypes } from 'graphlit-client/dist/generated/graphql-types';

const graphlit = new Graphlit();

// Ingest an event with timestamp
const response = await graphlit.ingestEvent(
  'User completed onboarding tutorial',    // markdown (event description)
  'Onboarding Completed',                  // name
  'New user finished the onboarding flow', // description (optional)
  new Date('2025-01-15T10:30:00Z')        // eventDate (when it occurred)
);

const eventId = response.ingestEvent.id;
console.log(`Event ingested: ${eventId}`);

// Retrieve the event
const content = await graphlit.getContent(eventId);
console.log(`Event text: ${content.content.markdown}`);
console.log(`Event date: ${content.content.eventDate}`);
```

## Ingest event (snake\_case method)

response = await graphlit.ingestEvent( markdown="User completed onboarding tutorial", name="Onboarding Completed", description="New user finished the onboarding flow", event\_date=datetime(2025, 1, 15, 10, 30, 0) )

event\_id = response.ingest\_event.id if response.ingest\_event else None

````

**C#**:
```csharp
using Graphlit;
using System;

var client = new Graphlit();

// Ingest event (PascalCase method)
var response = await graphlit.IngestEvent(
    markdown: "User completed onboarding tutorial",
    name: "Onboarding Completed",
    description: "New user finished the onboarding flow",
    eventDate: new DateTime(2025, 1, 15, 10, 30, 0, DateTimeKind.Utc)
);

var eventId = response.IngestEvent?.Id;
````

### Parameters

#### Required

* **`markdown`** (string): Event description/content
  * Should be descriptive and searchable
  * Can include markdown formatting
  * This becomes the event's main content
* **`name`** (string): Display name for the event (optional but recommended)

#### Optional

* **`description`** (string): Additional description of the event
  * Provides context beyond the markdown content
* **`eventDate`** (Date/DateTime): When the event occurred
  * **Critical**: This is the temporal anchor for the event
  * Used for chronological ordering and time-based queries
  * Must be ISO 8601 format or Date object
  * If omitted, uses current time
* **`id`** (string): Custom ID for the event
* **`identifier`** (string): Custom identifier for deduplication
* **`collections`** (EntityReferenceInput\[]): Collections to organize events
* **`correlationId`** (string): For tracking in production systems

### Response

```typescript
{
  ingestEvent: {
    id: string;                // Event ID
    name: string;              // Name you provided
    state: ContentState;       // FINISHED
    type: ContentEVENT;  // Always EVENT
    markdown: string;          // The event content
    description?: string;      // Description if provided
    eventDate: Date;           // Event timestamp
  }
}
```

### Developer Hints

#### Event vs Text vs Memory: Key Differences

| Aspect            | ingestEvent               | ingestText        | ingestMemory      |
| ----------------- | ------------------------- | ----------------- | ----------------- |
| **Purpose**       | Time-series events        | General content   | Semantic memories |
| **Timestamp**     | eventDate (specific time) | creationDate only | creationDate only |
| **Use Case**      | Calendar events, logs     | Documents, notes  | AI agent memory   |
| **Query Pattern** | Time-based filtering      | Full-text search  | Semantic search   |
| **Content Type**  | `EVENT`                   | `TEXT`            | `MEMORY`          |

#### When to Use ingestEvent

Use `ingestEvent` when:

* Events have a specific timestamp (when it happened matters)
* Building a timeline or activity log
* Tracking calendar events or milestones
* Creating audit trails
* Need temporal queries (e.g., "what happened last week?")
* Event occurred at a specific point in time

Use `ingestText` when:

* Content is timeless (e.g., documentation)
* Timestamp is not meaningful
* Just storing reference information

Use `ingestMemory` when:

* Storing semantic memories for AI agents
* Building conversational context
* Don't need specific event timestamps

#### 🕐 Understanding Timestamps

```typescript
// Current time
const now = new Date();
await graphlit.ingestMemory('Event just happened', 'Current Event', now, undefined, undefined, true);

// Past event
const pastDate = new Date('2025-01-01T12:00:00Z');
await graphlit.ingestMemory('New Year celebration', 'New Year', pastDate, undefined, undefined, true);

// Future event (scheduled)
const futureDate = new Date('2025-12-31T23:59:59Z');
await graphlit.ingestMemory('Year-end review scheduled', 'Future Event', futureDate, undefined, undefined, true);
```

**Important**: Timestamps enable time-range queries when searching memories.

### Variations

#### 1. Ingesting User Activity Log

Track user actions for personalization:

```typescript
// Create a collection for user activities
const collectionResponse = await graphlit.createCollection({
  name: 'User Activity Log'
});

const collectionId = collectionResponse.createCollection.id;

// Log multiple activities
const activities = [
  { text: 'User logged in', name: 'Login', timestamp: new Date('2025-01-15T09:00:00Z') },
  { text: 'User viewed product page: Widget A', name: 'Page View', timestamp: new Date('2025-01-15T09:05:00Z') },
  { text: 'User added Widget A to cart', name: 'Add to Cart', timestamp: new Date('2025-01-15T09:10:00Z') },
  { text: 'User completed purchase: $99.99', name: 'Purchase', timestamp: new Date('2025-01-15T09:15:00Z') }
];

for (const activity of activities) {
  await graphlit.ingestMemory(
    activity.text,
    activity.name,
    activity.timestamp,
    undefined,
    [{ id: collectionId }],
    true
  );
}

// Now you can query activities by time range
const filter = {
  collections: [collectionId],
  dateRange: {
    from: new Date('2025-01-15T09:00:00Z'),
    to: new Date('2025-01-15T09:30:00Z')
  }
};

const results = await graphlit.queryContents(filter);
console.log(`Found ${results.contents.results.length} activities in time range`);
```

#### 2. Ingesting with Entity Extraction

Extract structured data from memory text:

```typescript
// Create extraction workflow
const workflowInput: WorkflowInput = {
  name: 'Extract Memory Entities',
  extraction: {
    jobs: [
      {
        connector: {
          type: EntityExtractionServiceTypes.ModelText,
          modelText: {
            extractedTypes: [
              ObservableTypes.Person,
              ObservableTypes.Organization,
              ObservableTypes.Place,
              ObservableTypes.Event
            ]
          }
        }
      }
    ]
  }
};

const workflowResponse = await graphlit.createWorkflow(workflowInput);

// Ingest memory with extraction
const response = await graphlit.ingestMemory(
  'Had lunch with Sarah Johnson at Cafe Roma to discuss the partnership with TechCorp',
  'Business Lunch',
  new Date('2025-01-15T12:00:00Z'),
  { id: workflowResponse.createWorkflow.id },
  undefined,
  true  // Must be synchronous for workflow
);

// Retrieve with extracted entities
const content = await graphlit.getContent(response.ingestMemory.id);
// Will extract: Person (Sarah Johnson), Place (Cafe Roma), Organization (TechCorp)
console.log(`Extracted ${content.content.observations?.length || 0} entities from memory`);
```

#### 3. Building Conversation History

Store conversation turns as memories:

```typescript
const conversationId = 'user-123';
const collectionResponse = await graphlit.createCollection({
  name: `Conversation History - ${conversationId}`
});

const collectionId = collectionResponse.createCollection.id;

// User message
await graphlit.ingestMemory(
  'User asked: What are the best practices for API rate limiting?',
  `${conversationId} - User Message`,
  new Date(),
  undefined,
  [{ id: collectionId }],
  true
);

// Assistant response
await graphlit.ingestMemory(
  'Assistant responded: Here are the key strategies for API rate limiting: 1. Token bucket algorithm...',
  `${conversationId} - Assistant Message`,
  new Date(),
  undefined,
  [{ id: collectionId }],
  true
);

// Later, retrieve full conversation history
const filter = {
  collections: [collectionId],
  orderBy: 'CREATION_DATE',
  orderDirection: 'ASC'
};

const history = await graphlit.queryContents(filter);
// Chronologically ordered conversation
```

#### 4. Importing Historical Data

Bulk import past events:

```typescript
// Import calendar events from external system
const calendarEvents = [
  { description: 'Team standup meeting', date: '2025-01-10T10:00:00Z' },
  { description: 'Client presentation', date: '2025-01-12T14:00:00Z' },
  { description: 'Code review session', date: '2025-01-14T15:30:00Z' }
];

for (const event of calendarEvents) {
  await graphlit.ingestMemory(
    event.description,
    'Calendar Event',
    new Date(event.date),
    undefined,
    undefined,
    false  // Asynchronous for bulk import
  );
}

console.log(`Imported ${calendarEvents.length} historical events`);
```

### Common Issues

**Issue**: Memories not appearing in chronological order\
**Solution**: Ensure timestamps are correctly set. Use `orderBy: 'CREATION_DATE'` when querying.

**Issue**: `timestamp` parameter not accepted\
**Solution**: Ensure you're using a Date object (JavaScript) or datetime (Python), not a string. Or use ISO 8601 string format.

**Issue**: Cannot filter memories by date range\
**Solution**: When querying, use `dateRange` filter with `from` and `to` timestamps.

**Issue**: Workflow not extracting entities from memories\
**Solution**: Ensure workflow `extraction.jobs[].connector.type` is set to `EntityExtractionServiceTypes.ModelText` for text-based memory extraction.

### Production Example

**Server-side memory ingestion**:

```typescript
const response = await graphlit.ingestMemory(
  text,
  name,
  timestamp,
  workflow ? { id: workflow } : undefined,
  collections?.map((id) => ({ id })),
  isSynchronous
);
```

**Activity logging pattern**:

```typescript
// Log user activity with current timestamp
await graphlit.ingestMemory(
  `User ${userId} completed action: ${actionName}`,
  `Activity: ${actionName}`,
  new Date(),  // Current time
  undefined,
  [{ id: activityCollectionId }],
  true
);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.graphlit.dev/api-guides/use-cases/content/content-ingest-event.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
