• Product Introduction
  • Quick Start
    • Agent Development
    • Importing a Git Repository
    • Starting From a Template
    • Direct Upload
    • Start with AI
  • Framework Guide
    • Agent
    • Frontends
      • Vite
      • React
      • Vue
      • Hugo
      • Other Frameworks
    • Backends
    • Full-stack
      • Next.js
      • Nuxt
      • Astro
      • React Router
      • SvelteKit
      • TanStack Start
      • Vike
    • Custom 404 Page
  • Project Guide
    • Project Management
    • edgeone.json
    • Configuring Cache
    • Building Output Configuration
    • Error Codes
  • Build Guide
  • Deployment Guide
    • Overview
    • Create Deploys
    • Manage Deploys
    • Deploy Button
    • Using Github Actions
    • Using Gitlab CI/CD
    • Using CNB Plugin
    • Using IDE PlugIn
    • Using CodeBuddy IDE
  • Domain Management
    • Overview
    • Custom Domain
    • HTTPS Configuration
      • Overview
      • Apply for Free Certificate
      • Using Managed SSL Certificate
    • Configure DNS CNAME Record
  • Observability
    • Overview
    • Metric Analysis
    • Log Analysis
  • Functions
    • Overview
    • Edge Functions
    • Cloud Functions
      • Overview
      • Node.js
      • Python
      • Go
  • Agents
    • Overview
    • Quick Start
    • Conversation Storage
    • Observability
    • Sandbox Tool
      • Overview
      • Using the Agent Framework
      • Sandbox Atomic API
      • Network Search Tool
    • Agent Authentication
  • Models
    • Overview
    • Models and Vendors
      • Overview
      • Using Vendor Keys
        • OpenAI
        • Anthropic
        • Google AI Studio
        • DeepSeek
        • MiniMax
        • Hunyuan
        • Zhipu
        • MoonShot AI
    • FAQs
  • Storage
    • Overview
    • KV
    • Blob
  • Middleware
  • AI Tools
    • MCP
    • Skills
    • Plugin
  • Copilot
    • Overview
    • Quick Start
  • API Token
  • EdgeOne CLI
  • Message Notification
  • Integration Guide
    • AI
      • Dialogue Large Models Integration
      • Large Models for Images Integration
    • Database
      • Supabase Integration
      • Pages KV Integration
    • Ecommerce
      • Shopify Integration
      • WooCommerce Integration
    • Payment
      • Stripe Integration
      • Integrating Paddle
    • CMS
      • WordPress Integration
      • Contentful Integration
      • Sanity Integration
      • Payload Integration
    • Authentication
      • Supabase Integration
      • Clerk Integration
  • Best Practices
    • AI Dialogue Deployment: Deploy Project with One Sentence Using Skill
    • Using General Large Model to Quickly Build AI Application
    • Use the DeepSeek model to quickly build a conversational AI site
    • Building an Ecommerce Platform with Shopify
    • Building a SaaS Site Using Supabase and Stripe
    • Building a Company Brand Site Quickly
    • How to Quickly Build a Blog Site
  • Migration Guides
    • Migrating from Vercel to EdgeOne Pages
    • Migrating from Cloudflare Pages to EdgeOne Pages
    • Migrating from Netlify to EdgeOne Pages
  • Troubleshooting
  • FAQs
  • Limits
  • Pricing
  • Contact Us
  • Release Notes

Conversation Storage

context.store is the built-in conversation storage capability of Makers Agent. It requires zero configuration to save and retrieve conversation history and provides native adaptation for Claude / OpenAI / LangGraph / DeepAgents Agent frameworks.
The underlying layer is built on the platform's Blob storage. The APIs for Node and Python are fully mirrored (JavaScript camelCase, Python snake_case). The framework integration section focuses on TypeScript, with each section including an equivalent Python sample.

Using in Two Runtimes

In the code within both the agents/ and cloud-functions/ directories, store points to the same data.
Directory
Access Point
Typical Use
agents/
context.store
Primary LLM conversation path, message appending, and Checkpointer
cloud-functions/
context.agent.store
Conversation list API and message query

Framework Integration

context.store provides both framework-native adapters and generic APIs.
framework
Recommended Usage
Entry Point (TS)
claude-sdk
Framework-native SessionStore
context.store.claudeSessionStore()
openai-sdk
Framework-native Session
context.store.openaiSession(sessionId)
langgraph
Framework-native Checkpointer + BaseStore
context.store.langgraphCheckpointer / .langgraphStore
deepagents
Reuse LangGraph Checkpointer + BaseStore
context.store.langgraphCheckpointer / .langgraphStore
crewai
Not supported. Use the generic API for self-management.
-

Claude Agent SDK

claudeSessionStore() returns an implementation of the SessionStore protocol (append / load / listSessions / delete / listSubkeys).
// typescript
const sessionStore = context.store.claudeSessionStore()

// python
session_store = context.store.claude_session_store()

OpenAI Agents SDK

openaiSession(sessionId, { maxItems }) returns an implementation of the Session protocol from the OpenAI Agents SDK (getItems / addItems / popItem / clearSession).
// typescript
const session = context.store.openaiSession(context.conversation_id)

// python
session = context.store.openai_session(context.conversation_id)

LangGraph

langgraphCheckpointer implements BaseCheckpointSaver (getTuple / list / put / putWrites). langgraphStore implements BaseStore (get / put / search / listNamespaces / batch). Semantic search is not currently supported by the search method of BaseStore.
// typescript
const checkpointer = context.store.langgraphCheckpointer
const store = context.store.langgraphStore

// python
checkpointer = context.store.langgraph_checkpointer
store = context.store.langgraph_store

DeepAgents

DeepAgents is built on LangGraph and directly reuses the two adapters: langgraphCheckpointer + langgraphStore.
// typescript
const checkpointer = context.store.langgraphCheckpointer
const store = context.store.langgraphStore

// python
checkpointer = context.store.langgraph_checkpointer
store = context.store.langgraph_store

CrewAI

CrewAI's built-in Memory has a strong dependency on a vector database (default: LanceDB + embedder). context.store currently lacks a vector layer. Conversation history can be managed using the generic API of context.store. Core capabilities such as multi-agent orchestration, task chains, and tool calling remain completely unaffected.

General APIs

Method Overview

All methods are attached to context.store. The Node side uses object destructuring for parameters (camelCase), while the Python side uses keyword arguments (snake_case). Their semantics are identical.
Node Method
Python Method
Description
appendMessage
append_message
Appends a message; automatically creates a conversation if it does not exist.
getMessages
get_messages
Retrieves a list of messages and supports cursor-based pagination.
updateMessage
update_message
Overwrites a specified message.
deleteMessage
delete_message
Deletes a single message.
clearMessages
clear_messages
Clears messages but retains conversation metadata.
getConversation
get_conversation
Retrieves conversation metadata.
listConversations
list_conversations
Lists conversations in descending order of lastMessageAt.
updateConversation
update_conversation
Updates conversation metadata with a shallow merge.
deleteConversation
delete_conversation
Deletes the entire conversation (irrecoverable).
toAnthropicMessages
to_anthropic_messages
Converts a list of messages to the Anthropic Messages format.
toOpenAIInput
to_openai_input
Converts a list of messages to the OpenAI Chat Completions format.

appendMessage / append_message

Append a message to the specified conversation. If the conversation does not exist, it is automatically created, and a user index is established as needed.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Business-side conversation ID, length ≤ 256 bytes
role
'user' | 'assistant' | 'system' | 'tool'
Yes
Message role
content
string | string[] | object
Yes
Message body, supporting plain text / string arrays / multimodal dict, with a serialized size ≤ 50 MB.
metadata
Record<string, any>
No
Business-defined fields (such as number of tokens, tool_call, source tags, and so on)
userId / user_id
string
No
Associated user. After being passed in, it is written to the user index to facilitate listing conversations by user.
Return Value
The messageId / message_id of the new message (in the format msg_xxx).
TS Example:
const messageId = await context.store.appendMessage({
conversationId: context.conversation_id,
role: 'user',
content: context.request.body.message,
userId: context.request.body.userId,
metadata: { source: 'web' },
})
Python example:
message_id = await context.store.append_message(
conversation_id=context.conversation_id,
role="user",
content=context.request.body["message"],
user_id=context.request.body.get("user_id"),
metadata={"source": "web"},
)

getMessages / get_messages

Retrieve the message list for a specified conversation, supporting cursor-based pagination. If the conversation does not exist, no exception is thrown and an empty list is returned. By default, the list is sorted in chronological order (order='asc', earliest first) to facilitate direct prompt assembly.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
limit
number
No
Number of items per page, default 20, range [1, 100].
order
'asc' | 'desc'
No
Sorting direction, default 'asc' (earliest first).
after
string
No
A cursor that fetches messages after the specified messageId; mutually exclusive with before.
before
string
No
A cursor that fetches messages before the specified messageId; mutually exclusive with after.
Return Value
list[Message] — A message array. An empty array [] is returned if the conversation does not exist.
TS Example:
const messages = await context.store.getMessages({
conversationId: context.conversation_id,
limit: 50,
})
const reply = await openai.chat.completions.create({
model: 'gpt-4o',
messages: context.store.toOpenAIInput(messages),
})
Python example:
messages = await context.store.get_messages(
conversation_id=context.conversation_id,
limit=50,
)
reply = await openai_client.chat.completions.create(
model="gpt-4o",
messages=context.store.to_openai_input(messages),
)

updateMessage / update_message

Overwrite a message. Only the fields you provide are overwritten, while fields not provided retain their original values. The updatedAt / updated_at timestamps are automatically refreshed.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
messageId / message_id
string
Yes
Target message ID
content
string | string[] | object
No
New content; retains the original value if not provided.
metadata
Record<string, any>
No
Overwrites the metadata entirely (not merged); retains the original value if not provided.
Return Value
Message — The complete, updated message object.
TS Example:
const updated = await context.store.updateMessage({
conversationId: context.conversation_id,
messageId: 'msg_abc123',
content: 'corrected answer',
metadata: { edited: true },
})
Python example:
updated = await context.store.update_message(
conversation_id=context.conversation_id,
message_id="msg_abc123",
content="corrected answer",
metadata={"edited": True},
)

deleteMessage / delete_message

Delete a single message.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
messageId / message_id
string
Yes
Target message ID
TS Example:
await context.store.deleteMessage({
conversationId: context.conversation_id,
messageId: 'msg_abc123',
})
Python example:
await context.store.delete_message(
conversation_id=context.conversation_id,
message_id="msg_abc123",
)

clearMessages / clear_messages

Clear all messages in the conversation, but retain the ConversationMeta. To delete it completely, use deleteConversation.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
TS Example:
await context.store.clearMessages({ conversationId: context.conversation_id })
Python example:
await context.store.clear_messages(conversation_id=context.conversation_id)

getConversation / get_conversation

Obtain conversation metadata.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
Return Value
ConversationMeta — Contains fields such as conversationId / createdAt / lastMessageAt / messageCount / metadata.
TS Example:
const meta = await context.store.getConversation({
conversationId: context.conversation_id,
})
console.log(meta.messageCount, meta.metadata?.title)
Python example:
meta = await context.store.get_conversation(
conversation_id=context.conversation_id,
)
print(meta.message_count, (meta.metadata or {}).get("title"))

listConversations / list_conversations

List conversations, sorted by lastMessageAt, with support for cursor-based pagination and user-based filtering.
Parameter
Parameter
Type
Required
Description
limit
number
No
Number of items per page, default 20, range [1, 100].
order
'asc' | 'desc'
No
Sorting direction, default 'desc' (latest first).
after
string
No
A cursor that passes the nextCursor returned from the previous page.
before
string
No
A cursor that passes the previousCursor returned from the previous page.
userId / user_id
string
No
Lists only the conversations under the specified user (hits the user index).
Return Value
ListConversationsResult{ items, nextCursor, previousCursor }.
TS Example:
const { items, nextCursor } = await context.store.listConversations({
userId: 'u_123',
limit: 20,
})
Python example:
result = await context.store.list_conversations(user_id="u_123", limit=20)
items, next_cursor = result.items, result.next_cursor

updateConversation / update_conversation

Shallow merge metadata: Identical keys are overwritten, while different keys are retained.
Parameter
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
metadata
Record<string, any>
Yes
Fields to be merged; the key is deleted when the value is null / None.
Return Value
ConversationMeta — The merged conversation metadata.
TS Example:
await context.store.updateConversation({
conversationId: context.conversation_id,
metadata: { title: 'Product Inquiry', tag: null }, // Sets the title and removes the tag.
})
Python example:
await context.store.update_conversation(
conversation_id=context.conversation_id,
metadata={"title": "Product Inquiry", "tag": None},
)

deleteConversation / delete_conversation

Delete the entire conversation and synchronously clean up the message index, conversation metadata, and global conversation index. This action is irreversible.
Parameter:
Parameter
Type
Required
Description
conversationId / conversation_id
string
Yes
Conversation ID
TS Example:
await context.store.deleteConversation({
conversationId: context.conversation_id,
})
Python example:
await context.store.delete_conversation(
conversation_id=context.conversation_id,
)

toAnthropicMessages / to_anthropic_messages

Convert the message list returned by getMessages into the format of the messages field for the Anthropic Messages API.
Parameter
Parameter
Type
Required
Description
messages
Message[]
Yes
Return result of getMessages / get_messages
Return Value
Array<{ role: string; content: unknown }> — This can be directly used as the input parameter for anthropic.messages.create({ messages }).
TS Example:
const history = await context.store.getMessages({
conversationId: context.conversation_id,
})
const resp = await anthropic.messages.create({
model: 'claude-sonnet-4',
max_tokens: 1024,
messages: context.store.toAnthropicMessages(history),
})
Python example:
history = await context.store.get_messages(
conversation_id=context.conversation_id,
)
resp = await anthropic_client.messages.create(
model="claude-sonnet-4",
max_tokens=1024,
messages=context.store.to_anthropic_messages(history),
)

toOpenAIInput / to_openai_input

Convert the message list returned by getMessages into the format of the messages field for the OpenAI Chat Completions API. Retain role values that belong to user / assistant / system / tool, and pass through the content field unchanged.
Parameter
Parameter
Type
Required
Description
messages
Message[]
Yes
Return result of getMessages / get_messages
Return Value
Array<{ role: string, content: any }> — This can be directly used as the input parameter for openai.chat.completions.create({ messages }).
TS Example:
const history = await context.store.getMessages({
conversationId: context.conversation_id,
})
const resp = await openai.chat.completions.create({
model: 'gpt-4o',
messages: context.store.toOpenAIInput(history),
})
Python example:
history = await context.store.get_messages(
conversation_id=context.conversation_id,
)
resp = await openai_client.chat.completions.create(
model="gpt-4o",
messages=context.store.to_openai_input(history),
)

Data Structure

interface Message {
messageId: string // msg_xxx (automatically generated by appendMessage)
role: 'user' | 'assistant' | 'system' | 'tool'
content: any // string / array / object (multimodal)
createdAt: number // Timestamp in milliseconds
metadata?: Record<string, any> // Custom (e.g., token count, tool_call, etc.)
updatedAt?: number // Present only after updateMessage
}

interface ConversationMeta {
conversationId: string
createdAt: number // Timestamp in milliseconds
lastMessageAt: number // Timestamp in milliseconds
messageCount: number
metadata?: Record<string, any> // Business-defined (e.g., title, user, tags, etc.)
}

interface ListConversationsResult {
items: ConversationMeta[]
nextCursor?: string // The cursor for the next page, to be passed to the after parameter.
previousCursor?: string // The cursor for the previous page, to be passed to the before parameter.
}
The Python-side fields are message_id / conversation_id / created_at / last_message_at / message_count / next_cursor / previous_cursor, and their overall structure is consistent.

Limits and Quotas

Item
Default Value
Exceedance Action
conversation_id length
≤ 256 characters
Throws a MemoryValidationError.
Size of a single content item
≤ 50 MB (after serialization)
Throws a MemoryValidationError.
Maximum Messages per Conversation
10000
Throws a MemoryQuotaExceededError.
limit Upper Bound
100
Throws a MemoryValidationError.
limit Lower Bound
1
Throws a MemoryValidationError.
For a single content item that is excessively large (such as long documents and raw image data), it is recommended to store it in object storage and pass the URL into the message.

Conversation Summary

getMessages can retrieve a maximum of 100 messages per call. For long conversations, the recommended practice is to keep the most recent N pieces of original text + compress earlier content into a summary, then assemble the prompt from the Store with each request. The Store itself does not call the LLM or generate summaries; it only provides the JSON container ConversationMeta.metadata.

Responsibility Division

Responsible Party
Task/Responsibility
Store
Provide the metadata JSON field + shallow merge writes. Define two keys: summary (summary text) and summarizedUntil (the messageId up to which summarization has been performed).
Business side
Determine when to summarize, invoke a cost-effective model to generate the summary, and call updateConversation to write back.
summary / summarizedUntil are conventional keys, not part of the schema. The Store simply stores them as arbitrary JSON. You can rename them, provided that the business logic maintains consistency before and after the change.

Implementation Example

You can use a cheaper model for summarization—compression + preserving key facts do not require the reasoning capabilities of a primary model. None of the four requirements in the prompt can be omitted; otherwise, issues such as divergent summaries, inclusion of casual greetings, language inconsistencies, and increasingly lengthy summaries may occur.
async function summarizeWithLLM(previousSummary, newMessages) {
const transcript = newMessages
.filter(m => m.role === 'user' || m.role === 'assistant')
.map(m => `${m.role}: ${
typeof m.content === 'string' ? m.content : JSON.stringify(m.content)
}`)
.join('\n')
const prompt = previousSummary
? `Below are the [Existing Summary] and [New Dialogue] of a conversation. Please merge them into a new summary.
Requirements:
- Retain: key facts, user preferences, incomplete tasks, and important contextual settings.
- Delete: casual greetings, acknowledgments of receipt, duplicate content, and tool invocation details.
- Write in the same language as the most recent conversation.
- Keep it within 500 words.

[Existing Summary]
${previousSummary}

[New Dialogue]
${transcript}

[New Summary]`
: `Please summarize the following conversation into a summary.
Requirements:
- Retain: key facts, user preferences, incomplete tasks, and important contextual settings.
- Delete: casual greetings, acknowledgments of receipt, duplicate content, and tool invocation details.
- Write in the same language as the conversation.
- Keep it within 500 words.

[Dialogue]
${transcript}
[Summary]`
const { text } = await generateText({
model: openai('gpt-4o-mini'),
prompt,
maxTokens: 800,
})
return text.trim()
}

ai-agent
Bạn có thể hỏi tôi như
Tôi có thể triển khai những loại ứng dụng nào?