Skip to Content
DocsCore Components

Working with Documents

This example demonstrates how to create and update documents in Loopstack using the create_document, update_document, and load_document tools. We’ll build a workflow that manages customer profiles, showing how documents can be created with initial data and then updated with additional information.

Document Definition

First, let’s define a customer profile document that will serve as our template:

documents: - name: customer_profile description: "Customer information and preferences" schema: type: object properties: name: title: "Name" type: string email: title: "Email" type: string format: email status: title: "Status" type: string enum: ["prospect", "active", "inactive"] metadata: title: "Metadata" type: object properties: source: title: "Source" type: string required: - name - email - status content: status: "prospect" metadata: source: "unknown" ui: order: - name - email - status - metadata

Step 1: Create and Update Customer Profile

The first workflow creates a new customer profile document with initial data and then updates it within the same workflow:

workflows: - name: create_profile title: "Create Customer Profile" type: stateMachine transitions: # Create the initial document - name: create_initial_profile from: start to: profile_created call: - tool: create_document arguments: document: customer_profile # Reference to document template content: # Content object to merge with template name: "John Smith" email: "john.smith@example.com" metadata: source: "website_signup" # Override template default as: CREATED_PROFILE # Store document reference # Update the document from the same workflow - name: update_status from: profile_created to: profile_updated call: - tool: load_document arguments: where: name: customer_profile as: LOADED_PROFILE - tool: update_document arguments: id: ${ LOADED_PROFILE.id } # Use ID from loaded document content: status: "active" # Update status as: UPDATED_PROFILE - name: log_result from: profile_updated to: end call: - tool: create_chat_message arguments: role: assistant content: | βœ… Customer profile created successfully! **Profile Details:** - Name: {{ UPDATED_PROFILE.content.name }} - Email: {{ UPDATED_PROFILE.content.email }} - Status: {{ UPDATED_PROFILE.content.status }}

Key Concepts:

  • Document Reference: document: customer_profile references the document template
  • Content Merging: The content object merges with the template’s default content
  • Override Behavior: Specified values override template defaults (e.g., source: "website_signup")
  • Export Patterns: Use as for workflow-local data
  • Document Updates: Within the same workflow, you can update documents using update_document

Step 2: Cross-Workflow Document Handling

The second workflow demonstrates how to handle documents across different workflows. Since we cannot directly update documents from other workflows, we create a new document with updated content:

workflows: - name: update_profile title: "Update Customer Profile" type: stateMachine transitions: # Load existing document and create updated version - name: update_profile from: start to: profile_updated call: - tool: load_document arguments: where: name: customer_profile as: LOADED_PROFILE # Create new document with updated content - tool: create_document arguments: document: customer_profile content: # Content object to merge with template name: ${ LOADED_PROFILE.content.name } email: ${ LOADED_PROFILE.content.email } metadata: source: ${ LOADED_PROFILE.content.metadata.source } status: 'inactive' # We are setting the profile to inactive as: UPDATED_PROFILE - name: log_result from: profile_updated to: end call: - tool: create_chat_message arguments: role: assistant content: | βœ… Customer profile updated successfully! **Updated Information:** - Status: {{ UPDATED_PROFILE.content.status }}

Key Concepts:

  • Cross-Workflow Limitations: Documents cannot be directly updated across workflows
  • Document Loading: Use load_document with where conditions to find existing documents
  • Replace Document: When direct updates aren’t possible, create the document again
  • Newest Document: load_document will always load the newest document when multiple exists from different workflows

Document Loading Patterns

Load by Document Name

- tool: load_document arguments: where: name: customer_profile # Load by document template name

Load by Document ID

- tool: load_document arguments: where: id: ${ CREATED_PROFILE.id } # Load by specific document ID

Note: We always only query within the current root pipeline context. Documents are not designed to be accessed cross root pipeline executions although such queries are technically possible using the global flag. For storing data permanently and accessing them through different root pipeline runs, implement a custom data storage mechanism using custom tools.

Variable Interpolation Syntax

The examples use two different interpolation syntaxes:

  • Single Braces: ${ variable } - For accessing variables and object properties directly
  • Double Braces: {{ variable }} - For rendering variables in content and messages using Handlebars syntax.

Best Practices

  • Use Document Templates: Define document schemas for data validation and structure
  • Within-Workflow Updates: Use update_document for modifications within the same workflow
  • Cross-Workflow Handling: Use load_document + create_document pattern for cross-workflow scenarios
  • Content Merging: Understand how template defaults merge with provided content
  • Explicit Field Mapping: When recreating documents, explicitly map fields rather than using spread operators

Running This Example

This example is available in Loopstack Studio:

  1. Navigate to the Studio interface
  2. Switch to the examples workspace
  3. Select β€œExample 6: Working with Documents”
  4. Watch as documents are created, updated, and displayed

Complete Example:

include: - core/tools/create-chat-message.yaml - core/tools/create-document.yaml - core/tools/update-document.yaml - core/tools/load-document.yaml documents: - name: customer_profile description: "Customer information and preferences" schema: type: object properties: name: title: "Name" type: string email: title: "Email" type: string format: email status: title: "Status" type: string enum: ["prospect", "active", "inactive"] metadata: title: "Metadata" type: object properties: source: title: "Source" type: string required: - name - email - status content: status: "prospect" metadata: source: "unknown" ui: order: - name - email - status - metadata pipelines: - name: documents_example title: "Example 6: Working with Documents" type: root workspace: examples sequence: - workflow: create_profile - workflow: update_profile workflows: - name: create_profile title: "Create Customer Profile" type: stateMachine transitions: # Create the initial document - name: create_initial_profile from: start to: profile_created call: - tool: create_document arguments: document: customer_profile # Reference to document template content: # Content object to merge with template name: "John Smith" email: "john.smith@example.com" # Override template default metadata: source: "website_signup" as: CREATED_PROFILE # Store document reference # Update a document from the same workflow - name: update_status from: profile_created to: profile_updated call: - tool: load_document arguments: where: name: customer_profile as: LOADED_PROFILE - tool: update_document arguments: id: ${ LOADED_PROFILE.id } # Use ID from loaded document content: status: "active" # Update status as: UPDATED_PROFILE - name: log_result from: profile_updated to: end call: - tool: create_chat_message arguments: role: assistant content: | βœ… Customer profile created successfully! **Profile Details:** - Name: {{ UPDATED_PROFILE.content.name }} - Email: {{ UPDATED_PROFILE.content.email }} - Status: {{ UPDATED_PROFILE.content.status }} - name: update_profile title: "Update Customer Profile" type: stateMachine transitions: # We cannot update a document from another workflow # So we create a new document instead of updating it - name: update_profile from: start to: profile_updated call: - tool: load_document arguments: where: name: customer_profile as: LOADED_PROFILE - tool: create_document arguments: document: customer_profile content: # Content object to merge with template name: ${ LOADED_PROFILE.content.name } email: ${ LOADED_PROFILE.content.email } metadata: source: ${ LOADED_PROFILE.content.metadata.source } status: 'inactive' as: UPDATED_PROFILE - name: log_result from: profile_updated to: end call: - tool: create_chat_message arguments: role: assistant content: | βœ… Customer profile updated successfully! **Updated Information:** - Status: {{ UPDATED_PROFILE.content.status }}
Last updated on