Properties

Version: 6.0.0

Overview

Properties are EDDI's primary mechanism for storing and retrieving state within and across conversations. They are key-value pairs that can be set by agent configuration, extracted from API responses, or written by LLM tools — and they're accessible in every template (system prompts, HTTP call bodies, output templates, property instructions).

Properties are the glue that connects the pipeline's processing steps with persistent user state. Understanding how they work is essential for building stateful agents.

Key Concepts

What Properties Are

A property has:

  • Name (key): The identifier used to access the property (e.g., preferred_language, company_name)

  • Value: Can be a String, Integer, Float, Map, List, or Boolean

  • Scope: How long the property lives

  • Visibility (v6): Who can see the property

Property vs Context vs Memory

Mechanism
Source
Lifetime
Access Pattern

Properties

Agent-set (via PropertySetter, LLM tools)

Configurable (step → longTerm)

{properties.key.valueString}

Context

Your application (passed per request)

Per request

{context.key}

Memory

Pipeline (each task writes data)

Per step (current turn's data)

{memory.current.key}

Use properties when the agent needs to remember something. Use context when your application injects something. Use memory when you need data from the current or previous pipeline step.


Scopes

Properties support four scopes that control their lifetime:

Scope
Lifetime
Persistence
Use Case

step

Current conversation turn only

Not persisted

Temporary data needed only for this response

conversation

Entire conversation session

Persisted in conversation memory

User preferences within a session, extracted entities

longTerm

Across conversations

Persisted in user property store

User profile data, preferences that should survive between sessions

secret

Across conversations (encrypted)

Persisted via SecretsVault

API keys, tokens, sensitive credentials

Choosing the Right Scope


Visibility (v6)

Properties also have a visibility dimension that controls which agents can see them:

Visibility
Who sees it
Use Case

self (default)

Only the owning agent

Agent-specific preferences, internal state

group

All agents in the same group conversation

Shared context in multi-agent orchestration

global

All agents for this user

Cross-agent user preferences (e.g., language, timezone)

Visibility is orthogonal to scope — a property can be longTerm + self (persists across sessions, visible only to the owning agent) or longTerm + global (persists and visible to all agents).


Setting Properties

Via PropertySetter Configuration (JSON)

The PropertySetter task (ai.labs.property) sets properties based on triggered actions:

When the greet_user action fires:

  1. greeted is set to "true" for this conversation session

  2. preferred_language is set from the input context and persisted across all conversations and agents

Via Pre/Post Request Instructions

Properties can be set before or after any lifecycle task (HTTP calls, LLM calls):

Via LLM Tools (Agent-Driven)

When enableMemoryTools is enabled in the agent configuration, the LLM can set properties using built-in memory tools:

See Persistent User Memory for full details on the LLM memory tools, visibility scoping, and Dream consolidation.


Accessing Properties in Templates

Properties are available in all templates via the properties namespace:

In Output Templates

In System Prompts (LLM)

In HTTP Call Bodies

Property Value Accessors

Accessor
Type
Example

.valueString

String value

{properties.name.valueString}

.valueInt

Integer value

{properties.age.valueInt}

.valueFloat

Float value

{properties.score.valueFloat}

.valueObject

Object/Map

{properties.profile.valueObject.email}

.valueList

List

{#for item in properties.tags.valueList}...{/for}

.valueBoolean

Boolean

{#if properties.isPremium.valueBoolean}...{/if}


Property Lifecycle

Properties are managed by Conversation.java at session boundaries — NOT by pipeline tasks.

1. Conversation Init

Recall order (most_recent or most_accessed) and max entries come from the agent's UserMemoryConfig if configured, otherwise sensible defaults (1000 entries, most recent).

2. Pipeline Execution

3. Conversation Teardown

Key insight: Persistent state is a session concern handled at init/teardown — NOT in the pipeline. This means properties "just work" without any task ordering dependencies.

Storage: In v6, all persistent properties are stored in the unified usermemories collection (MongoDB) or usermemories table (PostgreSQL). The legacy properties collection has been removed. See Persistent User Memory for the full unified memory model.


Secret Properties

Properties with scope=secret are automatically handled by the SecretsVault:

  1. During pipeline execution, the secret value is available in memory normally

  2. At teardown, the value is encrypted and stored in SecretsVault

  3. The in-memory property value is scrubbed (replaced with a vault reference)

  4. On next conversation init, the value is loaded from the vault and decrypted

See Secrets Vault for full documentation.


Best Practices

1. Use Appropriate Scopes

2. Use fromObjectPath for Extraction

Instead of storing entire API responses, extract only what you need:

3. Use Visibility for Multi-Agent Scenarios

4. Naming Conventions

  • Use snake_case for property names

  • Use descriptive, specific names (user_preferred_timezone not tz)

  • Prefix agent-specific properties with the agent's domain (support_ticket_id, onboarding_step)


Last updated

Was this helpful?