Designing a Flexible Cognitive Architecture for Human-Computer Interaction
In developing the Vox Manifestor app, I faced a fundamental challenge: how could I create an effective system for representing information exchanged between an AI assistant and a human user? As a cognitive scientist, I knew that the next generation of operating systems needs to work in harmony with how the human brain processes information, not against it.
Gregory Bateson's insight that information is essentially "news of difference" - that we understand things through contrast rather than absolute states - provided a crucial starting point. When we're helping someone achieve a goal, one of the most useful contrasts we can draw is between their present state and their desired state. This comparison naturally generates the kind of differences that Bateson identified as meaningful information.
I needed a way to represent this information that would be:
Simple enough for users to work with
Structured enough for the app's AI brain (an LLM) to process
Flexible enough to handle various types of cognitive content
Scalable for future development
The solution I arrived at was the "Concept" - a simple but flexible structure that could represent any coherent chunk of cognitive information. Of course right now, I’m interested in representing information in textual format, as we’re using voice recognition as our main interface, and a language model as our ‘brain.’
At its most basic, a Concept is just a list of elements grouped together in a list. It’s basic, but we need to start somewhere.
CORE DESIGN PRINCIPLES:
Each Concept is fundamentally a self-contained circular node containing a list of text items
Initial focus is on Present → Desired state comparison as the simplest useful implementation
Keep the list size manageable (3-5 items) for cognitive manageability
Design for agent-assisted construction and editing of concepts
Build for future extensibility while maintaining current simplicity
Agent Interface
Voice interface for concept construction
Simple question-answer format for building lists
Clear conversation states for editing/viewing
Technical Implementation
The structure of a ‘Concept’:
data class Concept(
val id: String,
val type: ConceptType,
val items: List<ConceptItem>,
val properties: Map<String, Any> = emptyMap()
)
The Concept Type system allows us to distinguish between different kinds of information while maintaining a consistent interface. This in turn allows us to develop general processes for the agent to interact with the user and with whatever the current data structure is.
sealed class ConceptType {
object Present : ConceptType()
object Desired : ConceptType()
}
For example, you could process different types distinctly while using the same storage structure:
fun processConcept(concept: Concept) {
when (concept.type) {
is ConceptType.Milestone -> {
concept.items.forEach { item ->
val milestoneInfo = item.asMilestone()
// Process milestone-specific data
}
}
is ConceptType.Resource -> {
concept.items.forEach { item ->
val resourceInfo = item.asResource()
// Process resource-specific data
}
}
is ConceptType.Sensory -> {
// Process sensory data
when (concept.type) {
is ConceptType.Sensory.Visual -> // Handle visual
is ConceptType.Sensory.Auditory -> // Handle auditory
else -> // Handle other sensory types
}
}
else -> {
// Handle other types
}
}
}
Where ordinarily I would be creating individual Entities, each with their own table and unique data class, the Concept data structure makes explicit the knowledge that all the types of data we work with this in app are going to be essentially the same; lists of verbally presented information that can be easily accessed and edited by a language model.
This means that once we create a system for the language model / agent to edit one such list, we can multiply this process out ad infinitum for any content we desire. So it becomes a general method to facilitate interaction, communication, and mutual representation of information between the user and the agent.
Extensible Concepts: Properties and Metadata fields
So while the Concept itself has a Properties field, the individual elements that compose that Concept, its list items, (ConceptItems) have Metadata fields. Essentially they are the same, but allow us to store information at different hierarchical levels. We could probably use these metadata fields ultimately to link concepts together in deeper hierarchical trees if deemed necessary.
Here's how we might use the JSON properties field, specifically for Present/Desired state concepts:
// Present state concept with metadata
val presentConcept = Concept(
id = UUID.randomUUID().toString(),
type = ConceptType.Present,
items = listOf(/* state descriptions */),
properties = mapOf(
"createdAt" to System.currentTimeMillis(),
"lastModified" to System.currentTimeMillis(),
"emotionalIntensity" to 7, // How strongly felt is this state
"domainOfLife" to "career", // What life area does this relate to
"urgencyLevel" to 8 // How urgent is change needed
)
)
// Desired state concept with metadata
val desiredConcept = Concept(
id = UUID.randomUUID().toString(),
type = ConceptType.Desired,
properties = mapOf(
"targetDate" to SimpleDateFormat("yyyy-MM-dd").parse("2024-12-31").time,
"confidence" to 8, // How confident in achieving this
"clarity" to 6, // How clear is the vision
"impactLevel" to 9, // Expected impact when achieved
"linkedGoals" to listOf("goal1", "goal2") // Related manifestations
)
)
// Helper functions for type-safe property access
fun Concept.getEmotionalIntensity(): Int = getProperty("emotionalIntensity", 0)
fun Concept.getTargetDate(): Date? = getProperty<Long>("targetDate", null)?.let { Date(it) }
fun Concept.getConfidence(): Int = getProperty("confidence", 0)
// Example usage in UI or agent logic
if (presentConcept.getEmotionalIntensity() > 7 && desiredConcept.getConfidence() > 5) {
// High emotional intensity and confidence suggests strong motivation
// Agent could use this to adjust its conversation strategy
}
This allows us to:
Store relevant metadata without cluttering the base structure
Add new properties as we discover new needs
Keep type safety through helper functions
Support agent decision-making with rich metadata
Track temporal aspects of concept evolution
We can also store
So the ConceptType can be extended to include all these different types while keeping the same underlying structure.
// Example usage for different concept types
object ConceptExamples {
val milestonesConcept = Concept(
id = "milestone-1",
type = ConceptType.Milestone,
items = listOf(
ConceptItem(
id = "m1",
content = "Complete first draft",
metadata = mapOf(
"timeframe" to "2 weeks",
"dependsOn" to emptyList<String>()
)
)
)
)
val resourcesConcept = Concept(
id = "resources-1",
type = ConceptType.Resource,
items = listOf(
ConceptItem(
id = "r1",
content = "Writing software",
metadata = mapOf(
"availability" to "owned",
"cost" to 0
)
)
)
)
val ecologyConcept = Concept(
id = "ecology-1",
type = ConceptType.Intention,
items = listOf(
ConceptItem(
id = "i1",
content = "Improve writing skills",
metadata = mapOf(
"impact" to "positive",
"scope" to "personal"
)
)
)
)
val sensoryConcept = Concept(
id = "sensory-1",
type = ConceptType.Sensory.Visual,
items = listOf(
ConceptItem(
id = "s1",
content = "See myself typing confidently",
metadata = mapOf(
"intensity" to 8,
"clarity" to "vivid"
)
)
)
)
}
// Helper extension for type-specific metadata
fun ConceptItem.asMilestone(): MilestoneInfo {
return MilestoneInfo(
timeframe = metadata["timeframe"] as? String ?: "",
dependsOn = metadata["dependsOn"] as? List<String> ?: emptyList()
)
}
fun ConceptItem.asResource(): ResourceInfo {
return ResourceInfo(
availability = metadata["availability"] as? String ?: "unknown",
cost = metadata["cost"] as? Int ?: 0
)
}
// Type-specific data classes for cleaner access
data class MilestoneInfo(
val timeframe: String,
val dependsOn: List<String>
)
data class ResourceInfo(
val availability: String,
val cost: Int
)
Key benefits of this approach:
Consistent Structure: All types use the same Concept and ConceptItem classes
Flexible Metadata: Each type can have its own specific metadata needs
Type Safety: The sealed ConceptType class helps catch all cases in when expressions
Easy Extension: New types can be added by extending ConceptType
Type-Specific Processing: Helper extensions can provide type-safe access to metadata
Common use cases for metadata include:
Timestamps (creation, modification)
Priority levels
Categories/tags
Progress tracking
Emotional content
User-specific data
Feature flags
Sorting/filtering criteria
By using metadata, we can:
Add new features without database migrations
Store item-specific information without cluttering the main data structure
Support different types of items with different metadata needs
Enable feature discovery (checking if certain metadata exists)
The empty default (emptyMap()
) means items don't require any metadata, keeping simple items simple while allowing complexity when needed.
The properties map serves as a flexible extension mechanism in the Concept structure. Here's the thinking:
- Flexible Metadata
Rather than adding specific fields to the Concept class for every possible property
We can store any kind of additional information without changing the base structure
The Map<String, Any> type allows for any key-value pairs
- Use Cases:
// Store creation time
properties = mapOf("createdAt" to System.currentTimeMillis())
// Store position information
properties = mapOf("xPos" to 100, "yPos" to 200)
// Store UI state
properties = mapOf("isExpanded" to true)
// Store multiple properties
properties = mapOf(
"author" to "user1",
"lastModified" to timestamp,
"isLocked" to false
)
- Why
emptyMap()
default:
Not every concept needs properties
Keeps the basic creation simple
No null checking needed
Memory efficient when properties aren't needed
- Type Safety Consideration: While
Any
seems loose, we can create type-safe accessors:
fun <T> Concept.getProperty(key: String, default: T): T {
@Suppress("UNCHECKED_CAST")
return properties[key] as? T ?: default
}
This gives us future extensibility without complicating the base structure. We can add new capabilities by just using new property keys rather than changing the data structure.
Working with the Brain
The human brain's working memory can typically handle about 4-7 chunks of information at once. I designed the Concept structure to work within these limitations. Each Concept contains a small number of items, and related Concepts can be linked together without overwhelming the user's cognitive capacity.
This approach has proven particularly effective in the context of goal-setting and manifestation. When a user wants to achieve something, we can break down the goal into multiple Concepts:
Present state: "Where am I now?"
Desired state: "Where do I want to be?"
Resources: "What do I have that can help?"
Milestones: "What are the steps along the way?"
Each of these is represented by the same underlying structure but can be processed and displayed differently based on its type.
The AI Perspective
What's particularly interesting about this architecture is how well it works for both human and AI understanding. The LLM can easily process and reason about these structured chunks of information, while humans can interact with them naturally through conversation.
For example, when collecting information about a present state, the AI can ask focused questions and store the responses as discrete items within a Concept. This creates a clear, structured representation of the user's current situation that can later be contrasted with their desired state.
Future Implications
As I continue developing this system, I'm increasingly excited about its potential applications beyond just goal manifestation. This architecture could serve as a foundation for more sophisticated human-AI collaboration:
AI Working Memory: The Concept structure could function as a form of working memory for AI systems, allowing them to maintain and manipulate contextual information during interactions.
Shared Understanding: By using the same structural representations, humans and AIs can build shared mental models more effectively.
Hierarchical Knowledge: The system can be extended to support hierarchical relationships between Concepts, enabling more complex knowledge representation while maintaining cognitive manageability.
Multimodal Integration: Future versions could incorporate different types of data - images, sounds, spatial information - while maintaining the same basic structural approach.
Some thoughts…
Simple structures, properly designed, can represent complex cognitive information
Respecting human cognitive limitations should improve usability without sacrificing depth
The future of human-AI interaction will require shared cognitive frameworks
As we move toward more sophisticated AI systems, I believe architectures that are designed to work with both human and machine cognition - will become increasingly important. The challenge isn't just to make AI systems more powerful, but to create interfaces that allow humans and AIs to work together effectively, sharing understanding and building knowledge collaboratively.
Forward: Evolving the Concept Architecture
Having developed the initial Concept architecture for the Vox Manifestor app as a way to represent goal-related information between humans and AI, I can now see clear paths for the evolution of the basic structure - organizing information into cognitively manageable chunks based on Bateson's principle of "difference that makes a difference."
How the concept architecture may expand in time
Hierarchical Extension
Implement parent-child relationships between Concepts
Maintain cognitive manageability at each level
Enable collapsible/expandable views of knowledge structures
Dynamic Adaptation
Adjust information granularity based on user cognitive load
Adapt presentation based on user expertise
Support different levels of detail for different contexts
Collaborative Features
Enable multiple humans and AIs to work with shared Concept structures
Maintain individual perspectives within collective knowledge
Track contributions and changes over time
Multimodal Integration
Expand beyond text to include visual, auditory, and spatial information
Maintain consistent structure across different modalities
Enable cross-modal relationships and insights
Implementation Guidelines
Keep the basic Concept structure simple and consistent
Add complexity through relationships rather than base structure
Maintain focus on cognitive manageability
Ensure all additions serve practical user needs
Preserve easy AI processability
Technical Foundations
// Core structure remains unchanged but extensible
data class Concept(
val id: String,
val type: ConceptType,
val items: List<ConceptItem>,
val properties: Map<String, Any> = emptyMap(),
val relationships: List<ConceptRelation> = emptyList() // New addition
)
The key is to evolve the architecture while maintaining its fundamental simplicity and effectiveness as a bridge between human and machine cognition. Each addition should enhance either understanding or collaboration without increasing cognitive load.
This architecture has the potential to become a standard for human-AI cognitive collaboration, but only if we maintain its core principles of simplicity, manageability, and shared understanding.