Cogs in AgentForge are declarative YAML-driven orchestrators that define multi-agent workflows, memory nodes, and branching logic—enabling complex, loopable, and branching AI pipelines without writing custom Python code.
A Cog is:
- A YAML file under
.agentforge/cogs/that declares agents, memory nodes, and flow logic. - A fully declarative automation: no custom Python is required to configure agent interactions.
- An engine for chaining agents, injecting persona/memory context, and handling routing based on agent outputs.
When you run a Cog, AgentForge:
- Loads and validates the YAML config.
- Initializes shared memory and persona context.
- Executes agents in the order defined by
flow.startandtransitions. - Merges each agent's output into the internal state.
- Routes to next agents via direct or decision-based transitions.
- Terminates when an
end: truenode is reached.
cog:
name: "ExampleFlow" # Identifier for this Cog
description: "A sample decision workflow."
agents: # Declare agent nodes
- id: analyze
description: "Extracts the useful facts from the request."
template_file: analyze_agent # Required: at least one of template_file or type
- id: decide
description: "Chooses the next workflow branch."
template_file: decide_agent
- id: respond
description: "Writes the final answer."
template_file: response_agent
memory: # (Optional) shared memory nodes
- id: general_memory
type: agentforge.storage.memory.Memory # Optional: defaults to base Memory
collection_id: history
query_before: [analyze]
update_after: [respond]
query_keys: [user_input]
update_keys: [respond]
flow: # Define execution order
start: "analyze"
transitions:
analyze: decide
decide:
choice:
"approve": respond
"reject": analyze
fallback: respond
max_visits: 5
respond:
end: truecog.name,cog.description: Metadata.agents: List of agent definitions:id: Unique node key (required).description: Optional human-readable metadata for docs, review, and tooling. It is preserved in structured config but is not passed to prompts or used for routing.template_file: Prompt YAML name (required iftypenot set).type: Full Python path to Agent subclass (required iftemplate_filenot set).
memory: List of memory nodes (optional):id: Key for memory instance (required).type: Memory class to instantiate (optional; defaults to base Memory).collection_id: Optional override for storage partition (defaults to node'sidfor base Memory; subclasses may override).query_before/update_after: List or string of agent IDs (always treated as lists internally).query_keys/update_keys: Keys to extract from context/state for querying/updating memory.
flow:start:agents.idto run first.transitions: Mapping from eachidto next steps:- Simple:
agentA: agentB - Decision: Use an output field (e.g.,
choice) to branch:agentA: choice: "approve": agentX "reject": agentY fallback: agentZ
- Loop Guard:
max_visitsprevents infinite cycling. - Terminate:
agent_id: end: truemarks a terminal node.
- Simple:
Decision-based transitions route flow based on values in the agent's output.
- Decision Key: The field name in the agent's output that determines the next branch.
- Value Normalization: Matching is case-insensitive and normalizes booleans/strings. Always quote branch labels in YAML to avoid type conversion issues.
- Fallback: If a decision value doesn't match, or the key is missing, or
max_visitsis exceeded, thefallbackbranch is used. If no fallback is defined, the flow terminates with an exception.
Memory nodes declared under memory are shared across all agents in a Cog. Each node can:
- Specify when to query or update (before/after specific agents)
- Use
query_keysandupdate_keysto control what data is used - Use a custom
typefor specialized memory behavior
Collection Naming:
- For base Memory,
collection_iddefaults to the node'sidif not specified. - Some subclasses (e.g., PersonaMemory) may override this logic and append suffixes or use different naming.
Automatic Chat History Memory:
- Unless
chat_memory_enabled: falseis set at the top level, achat_historymemory node is automatically added for you. - Configure the recency slice with
chat_history_max_results(default: 20,0= no limit) and the semantic slice withchat_history_max_retrieval(default: 20,0= disable semantic retrieval). - Access chat history in prompts with
{_mem.chat_history.history}(recent turns) and{_mem.chat_history.relevant}(semantically relevant turns).
Note: You do not need to define a
chat_historymemory node yourself—this is handled automatically when chat memory is enabled.
- Initialization: Cog builds a
contextdict (external input) and astatedict (internal agent outputs). - Agent Run: For each node, the agent is called with the current context and state.
- Collect Output: Agent result is stored in
state[node_id]. - Memory Query/Update: Memory is queried before and updated after agents as configured.
- Routing: Next node is selected via
flow.transitions[node_id]. - Loop Control: If a node's
max_visitsis exceeded, thefallbackbranch is used. - Completion: When
end: trueis reached,cog.run()returns the final state or specified output.
When an agent runs, the Cog engine provides three key variables in the prompt template context:
_ctx: The current external context, such as user input and any runtime values passed tocog.run()._state: The internal state dictionary, containing parsed outputs from all previously executed agents in the workflow._mem: The memory manager, where each memory node is accessible as an attribute. For example, if you have a memory node withid: persona_memory, you can access its properties in your prompt as{_mem.persona_memory.<property>}.
_ctx is not auto-parsed from JSON or YAML strings.
If a prompt needs nested context such as {_ctx.profile.name}, pass profile as a dictionary to Cog.run(profile={"name": "Ada"}) rather than as a JSON string.
Whole dictionaries and lists, including {_ctx} or {_state}, render as readable Markdown in prompts.
Agent outputs become structured data in _state when the agent prompt YAML sets parse_response_as, such as parse_response_as: json.
This allows agents to reference both current user input/context and the outputs of other agents. For example, in a prompt template:
prompts:
user:
context: |
## User Input
{_ctx.user_input}
analysis: |
## Previous Analysis
{_state.analysis}
persona_info: |
## Persona Info
{_mem.persona_memory._narrative}{_ctx.user_input}: Accesses the current user input or context value.{_state.analysis}: Accesses the output of theanalysisagent node.{_mem.persona_memory._narrative}: Accesses the contents of the persona narrative built by thePersonaMemorymemory node.
The Cog's run() method returns values based on the end keyword configuration:
- Default: Returns the internal state dictionary with all agent outputs.
end: true: Returns only the output of the last agent executed.end: "dot.notation.key": Returns a specific value from the state using dot notation.
Example:
transitions:
final_agent:
end: true # Returns only final_agent's outputOr using a specific key:
transitions:
final_agent:
end: "final_agent.summary" # Returns only the summary key from final_agent's outputThe Cog engine handles errors as follows:
- Invalid Transitions: If a transition points to a non-existent agent, an exception is raised.
- Missing Decision Keys/No Matching Branch: If the decision key is missing or the value doesn't match, the
fallbackbranch is used. If no fallback is defined, the flow terminates with an exception. - Loop Prevention: When
max_visitsis exceeded, thefallbackbranch is used. If no fallback, the flow terminates with an exception.
cog:
name: "SimpleAnalysis"
description: "Basic analysis flow"
agents:
- id: analyze
template_file: analyze_agent
flow:
start: analyze
transitions:
analyze:
end: truecog:
name: "AnalysisDecisionFlow"
description: "A multi-step workflow with decision branching"
agents:
- id: analyze
template_file: analyze_agent
- id: decide
template_file: decide_agent
- id: respond
template_file: response_agent
memory:
- id: general_memory
query_before: [analyze, respond]
update_after: [respond]
query_keys: [user_input]
update_keys: [user_input, respond]
flow:
start: analyze
transitions:
analyze: decide
decide:
choice:
"approve": respond
"reject": analyze
fallback: respond
max_visits: 3
respond:
end: true- Prompt Engineering: Structure prompts with clear sections and use memory in context sections.
- Decision Branches: Always quote branch names in YAML, set reasonable
max_visits, and definefallbackpaths. - Memory Management: Use
query_beforeandupdate_afterto control memory usage, and be explicit aboutquery_keysandupdate_keys. Use{_mem.<node_id>.readable}in prompts for human-friendly formatting. - Chat History: Leverage the automatic
chat_historymemory node for conversation context unless explicitly disabled. - Testing: Use
cog.get_track_flow_trail()to inspect execution order and outputs.