Properties
Version: 6.2.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, orBooleanScope: How long the property lives
Visibility (v6): Who can see the property
Property vs Context vs Memory
Properties
Agent-set (via PropertySetter, LLM tools)
Configurable (step → longTerm)
{properties.key}
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:
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:
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:
greetedis set to"true"for this conversation sessionpreferred_languageis 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.
⚠️
propertiesexposes raw values, notPropertyobjects.MemoryItemConverter.convert()putsConversationProperties.toMap()into the template context, andtoMap()returns the unwrapped Java value that was stored (String,Integer,Float,Boolean,List,Map) — thePropertywrapper never reaches the template. Use{properties.key}directly. A.valueString/.valueInt/ … suffix resolves against the raw value (aStringhas novalueStringproperty) and fails at render time. ThevalueString,valueInt, … names are write-side field names of the JSON property-setter config only. AGENTS.md §5.1 is the authoritative reference for the template data model.
In Output Templates
In System Prompts (LLM)
In HTTP Call Bodies
Reading the Different Value Types
The property-setter config picks the value type by which value* field you write (valueString, valueInt, valueFloat, valueObject, valueList, valueBoolean). In templates, all of them are read the same way — through the property name:
valueString
{properties.name}
Hello {properties.name}
valueInt
{properties.age}
You are {properties.age}
valueFloat
{properties.score}
Score: {properties.score}
valueObject
{properties.profile.<field>}
{properties.profile.email}
valueList
{properties.tags}
{#for item in properties.tags}...{/for}
valueBoolean
{properties.isPremium}
{#if properties.isPremium}...{/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 the maximum number of recalled entries come from the agent's userMemoryConfig. The documented defaults are most_recent ordering and 50 entries — the field defaults of AgentConfiguration.UserMemoryConfig, which apply as soon as the agent declares a userMemoryConfig block, however small.
Known inconsistency: an agent with no
userMemoryConfigblock at all falls back to a separate hard-coded default inConversation(DEFAULT_MAX_RECALL_ENTRIES = 1000) rather than to the 50 above, so the effective cap silently changes by a factor of 20 depending on whether the block is present. Treat 50 as the intended default and setmaxRecallEntriesexplicitly if the number matters to you; unifying the two constants is tracked as a code fix.
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
usermemoriescollection (MongoDB) orusermemoriestable (PostgreSQL). The legacypropertiescollection 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:
During pipeline execution, the secret value is available in memory normally
At teardown, the value is encrypted and stored in SecretsVault
The in-memory property value is scrubbed (replaced with a vault reference)
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_casefor property namesUse descriptive, specific names (
user_preferred_timezonenottz)Prefix agent-specific properties with the agent's domain (
support_ticket_id,onboarding_step)
Related Documentation
Conversation Memory - How memory flows through the pipeline
Secrets Vault - Encrypted property storage
Passing Context Information - External data injection
Output Templating - Using properties in templates
LLM Integration - Using properties in LLM prompts
HTTP Calls - Using properties in API requests
Last updated
Was this helpful?