Skip to main content

Layout System Guide

Complete guide for using CrewX's layout system to create reusable, customizable prompt templates.

Table of Contents

Overview

CrewX layouts provide a way to create reusable prompt structure templates that can be shared across agents. Think of layouts as React components for AI prompts—they define the structure and accept customizable props.

What Are Layouts?

Layouts separate prompt structure (the container) from prompt content (the actual instructions):

AspectLayout (inline.layout)Prompt (inline.prompt)
PurposeDefines the structural templateContains agent-specific instructions
ReusabilityShared across multiple agentsUnique to each agent
CustomizationProps (like React PropTypes)Direct text content
ExampleSecurity containers, document sections"You are a code reviewer..."

Why Use Layouts?

Without layouts:

agents:
- id: agent1
inline:
prompt: |
<crewx_system_prompt>
{{{documents.manual.content}}}
</crewx_system_prompt>
<system_prompt key="{{vars.security_key}}">
You are agent 1...
</system_prompt>

- id: agent2
inline:
prompt: |
<crewx_system_prompt>
{{{documents.manual.content}}} # Duplicate structure
</crewx_system_prompt>
<system_prompt key="{{vars.security_key}}">
You are agent 2...
</system_prompt>

With layouts:

agents:
- id: agent1
inline:
layout: "crewx/default" # Reusable structure
prompt: |
You are agent 1...

- id: agent2
inline:
layout: "crewx/default" # Same structure, different content
prompt: |
You are agent 2...

Quick Start

Step 1: Choose a Layout

Start with a built-in layout:

agents:
- id: my_agent
inline:
layout: "crewx/default" # Simple string reference
prompt: |
You are a helpful assistant.

Step 2: Use Minimal Layout

For simple agents without full agent profile:

agents:
- id: simple_agent
inline:
layout: "crewx/minimal" # Lightweight wrapper
prompt: |
You are a simple assistant.

Step 3: Test Your Agent

crewx query "@simple_agent help me with my task"

That's it! You're using layouts.

Basic Usage

Using Built-in Layouts

Reference a layout by its ID:

agents:
- id: simple_agent
inline:
layout: "crewx/default" # String format
prompt: |
Your instructions here.

Available built-in layouts:

  • crewx/default - Full agent profile with security containers (default)
  • crewx/minimal - Minimal security wrapper only (lightweight)

Layout Selection

Choose the appropriate layout for your use case:

agents:
- id: full_agent
inline:
layout: "crewx/default" # Full agent profile
prompt: |
You are a complex agent with full capabilities.

- id: minimal_agent
inline:
layout: "crewx/minimal" # Minimal wrapper only
prompt: |
You are a simple, focused agent.

Default Behavior

If you omit layout, CrewX uses crewx/default automatically:

agents:
- id: my_agent
inline:
# No layout specified → uses crewx/default
prompt: |
Your instructions here.

Built-in Layouts

crewx/default

The standard layout used by all agents unless specified otherwise. Provides the full agent profile with complete context.

Structure:

  • Wraps prompt in <crewx_system_prompt> and <system_prompt> security containers
  • Includes full agent profile (identity, CLI options, session info)
  • Includes CrewX User Manual document
  • Injects agent's inline.prompt into secure container

Props: None

Usage:

agents:
- id: my_agent
inline:
layout: "crewx/default" # Explicit (or omit for default)
prompt: |
You are a helpful assistant.

When to use:

  • Standard agents that need full context and capabilities
  • Agents that benefit from complete agent profile information
  • Default choice for most use cases

crewx/minimal

A lightweight layout that provides only the essential security wrapper without the full agent profile.

Structure:

  • Wraps prompt in <crewx_system_prompt> and <system_prompt> security containers
  • Injects agent's inline.prompt directly (no additional context)
  • Minimal overhead for simple agents

Props: None

Usage:

agents:
- id: simple_agent
inline:
layout: "crewx/minimal" # Lightweight wrapper
prompt: |
You are a simple assistant.

When to use:

  • Simple agents with focused, specific tasks
  • When you want minimal system context
  • Performance-sensitive scenarios where you want to minimize token usage
  • Agents that don't need full agent profile information

Creating Custom Layouts

You can define custom layouts in your crewx.yaml file to create reusable prompt structures.

Basic Custom Layout

Define layouts in the layouts section of your crewx.yaml:

# crewx.yaml
layouts:
my_custom_layout: |
<system_prompt key="{{vars.security_key}}">
You are a specialized agent.

{{{agent.inline.prompt}}}

Always follow best practices.
</system_prompt>

agents:
- id: my_agent
inline:
layout: "my_custom_layout" # Reference your custom layout
prompt: |
You are a code reviewer focusing on security.

Simple Parameterized Layout

For layouts shared across multiple agents, include parameters directly in the prompt:

# crewx.yaml
layouts:
team_layout: |
<system_prompt key="{{vars.security_key}}">
You are a specialized team member.

{{{agent.inline.prompt}}}

Always collaborate with your team and follow best practices.
</system_prompt>

agents:
- id: frontend_dev
inline:
layout: "team_layout"
prompt: |
You are a member of the Frontend Team.
Your focus area: frontend
You specialize in React and TypeScript.

- id: backend_dev
inline:
layout: "team_layout"
prompt: |
You are a member of the Backend Team.
Your focus area: backend
You specialize in Node.js and databases.

Note: For most use cases, including parameters directly in the prompt field is simpler and more maintainable than using props validation.

Advanced: Layout with Props Validation

For advanced use cases requiring type validation and default values, use propsSchema:

# crewx.yaml
layouts:
config_layout:
propsSchema:
teamName:
type: string
defaultValue: "Development Team"
maxContextDocs:
type: number
min: 1
max: 50
defaultValue: 10
verbose:
type: bool
defaultValue: false
template: |
<system_prompt key="{{vars.security_key}}">
<team>{{props.teamName}}</team>
<context_limit>{{props.maxContextDocs}}</context_limit>
<verbose_mode>{{props.verbose}}</verbose_mode>

{{{agent.inline.prompt}}}

Follow team guidelines and best practices.
</system_prompt>

agents:
# Agent with default props
- id: default_agent
inline:
layout: "config_layout" # Uses default values
prompt: |
You are an agent with default settings.

# Agent with custom props
- id: custom_agent
inline:
layout:
id: "config_layout"
props:
teamName: "AI Research Team"
maxContextDocs: 25
verbose: true
prompt: |
You are an agent with custom settings.

When to use props validation:

  • Multiple agents need different configuration values
  • Type safety is important (number ranges, enums, booleans)
  • You want validation errors for invalid values
  • Shared layout across many agents with varying settings

Available Template Variables

Use these variables in your custom layouts:

  • {{{agent.inline.prompt}}} - Agent's prompt content
  • {{{agent.id}}}, {{{agent.name}}} - Agent metadata
  • {{vars.security_key}} - Security key for containers
  • {{{documents.doc-name.content}}} - Document content
  • {{props.yourPropName}} - Custom props
  • {{env.YOUR_ENV_VAR}} - Environment variables

Layout Best Practices

  1. Always use security containers: Wrap content in <system_prompt key="{{vars.security_key}}">
  2. Inject agent prompt: Use {{{agent.inline.prompt}}} with triple braces
  3. Provide defaults: Set defaultValue for all props
  4. Keep it simple: Start with minimal structure, add complexity only when needed
  5. Reuse common patterns: Extract repeated structures into layouts

Example: Documentation-focused Layout

layouts:
doc_reviewer_layout: |
<system_prompt key="{{vars.security_key}}">
<role>Documentation Reviewer</role>

<standards>
{{{documents.writing-guide.content}}}
</standards>

<instructions>
{{{agent.inline.prompt}}}
</instructions>

Always check for clarity, accuracy, and consistency.
</system_prompt>

documents:
writing-guide: |
# Writing Guide
- Use clear, concise language
- Include code examples
- Follow markdown conventions

agents:
- id: doc_reviewer
inline:
layout: "doc_reviewer_layout"
prompt: |
Review documentation for technical accuracy and readability.

Props Schema

Note: Built-in layouts (crewx/default and crewx/minimal) do not use props. This section is relevant when creating custom layouts.

CrewX uses React PropTypes-style validation for layout props. If you're familiar with React, this will feel natural.

Prop Types

String Props

propsSchema:
name:
type: string
defaultValue: "default"

With constraints:

propsSchema:
theme:
type: string
oneOf: ["light", "dark", "auto"] # Enum values
defaultValue: "auto"

Usage in a custom layout:

layout:
id: "my/custom-layout"
props:
theme: "dark" # Must be "light", "dark", or "auto"

Number Props

propsSchema:
maxItems:
type: number
min: 1
max: 100
defaultValue: 10

Usage in a custom layout:

layout:
id: "my/custom-layout"
props:
maxItems: 25 # Must be between 1 and 100

Boolean Props

propsSchema:
enabled:
type: bool
defaultValue: true

Usage in a custom layout:

layout:
id: "my/custom-layout"
props:
enabled: false

Array Props

Simple array:

propsSchema:
tags:
type: array
defaultValue: []

Typed array (arrayOf):

propsSchema:
sections:
type: arrayOf
itemType: string
itemOneOf: ["section1", "section2", "section3"]
defaultValue: ["section1"]

Usage in a custom layout:

layout:
id: "my/custom-layout"
props:
sections: ["section1", "section2"] # Each item must be valid

Required Props

Use isRequired to enforce mandatory props:

propsSchema:
userId:
type: string
isRequired: true # Must be provided

Usage in a custom layout:

layout:
id: "my/custom-layout"
props:
userId: "user123" # Required, cannot be omitted

Complex Example

propsSchema:
# String with enum constraint
theme:
type: string
oneOf: ["light", "dark", "auto"]
defaultValue: "auto"
description: "UI theme preference"

# Number with range constraint
maxDocs:
type: number
min: 1
max: 50
defaultValue: 10
description: "Maximum documents to load"

# Boolean flag
enableCache:
type: bool
defaultValue: true
description: "Enable response caching"

# Array of specific strings
features:
type: arrayOf
itemType: string
itemOneOf: ["search", "analytics", "reporting"]
defaultValue: ["search"]
description: "Enabled features"

# Required string
agentName:
type: string
isRequired: true
description: "Agent display name"

React PropTypes Comparison

If you know React PropTypes, here's the mapping:

React PropTypesCrewX SchemaExample
PropTypes.stringtype: stringname: "value"
PropTypes.numbertype: numbercount: 42
PropTypes.booltype: boolenabled: true
PropTypes.arraytype: arrayitems: [1, 2, 3]
PropTypes.arrayOf(PropTypes.string)type: arrayOf, itemType: stringtags: ["a", "b"]
PropTypes.oneOf(["a", "b"])oneOf: ["a", "b"]mode: "a"
.isRequiredisRequired: trueRequired field

Layout Resolution

Resolution Order

CrewX resolves layouts in two stages:

  1. Built-in layouts - Load from CrewX system (templates/agents/*.yaml)
  2. Props override - Apply user-provided props from crewx.yaml (for custom layouts with props)
┌─────────────────────────┐
│ Built-in Layout │ Step 1: Load base layout
│ (crewx/default or │ (default/minimal)
│ crewx/minimal) │
└───────────┬─────────────┘


┌─────────────────────────┐
│ Custom Layout Props │ Step 2: Apply props
│ (if using custom │ (custom layouts only)
│ layout) │
└─────────────────────────┘


┌─────────────────────────┐
│ Final Layout │ Result: Rendered layout
│ │ with agent prompt
└─────────────────────────┘

Props Override Example (Custom Layouts)

Custom layout defines:

# my-custom-layout.yaml (custom layout)
id: "my/custom-layout"
propsSchema:
theme:
type: string
defaultValue: "auto"
maxItems:
type: number
defaultValue: 10

User overrides in crewx.yaml:

# crewx.yaml (your project)
agents:
- id: my_agent
inline:
layout:
id: "my/custom-layout"
props:
theme: "dark" # Override: "auto" → "dark"
maxItems: 20 # Override: 10 → 20
prompt: |
Your instructions here.

Final rendered layout:

  • theme = "dark" (overridden)
  • maxItems = 20 (overridden)

Fallback Behavior

ScenarioBehaviorExample
Layout existsUse specified layoutlayout: "crewx/minimal" → loads minimal
Layout not foundFall back to crewx/defaultlayout: "unknown/layout" → uses default + warning
Props invalid (lenient mode)Use default values + warningInvalid prop → uses default value
Props invalid (strict mode)Error, execution stopsInvalid prop → throws error

Validation Modes

Lenient Mode (default):

  • Invalid props → Use default values
  • Unknown props → Ignore with warning
  • Missing required props → Use defaults if available

Strict Mode:

  • Invalid props → Throw validation error
  • Unknown props → Throw validation error
  • Missing required props → Throw validation error

Configuration is set by CrewX system, not user-configurable.

Best Practices

1. Start Simple

Begin with built-in layouts before creating custom ones:

# ✅ Good: Start with built-in
agents:
- id: my_agent
inline:
layout: "crewx/default"
prompt: |
Your instructions.

2. Use Meaningful Prop Names

Make props self-documenting:

# ✅ Good: Clear prop names
props:
maxContextDocuments: 20
enableConversationHistory: true

# ❌ Bad: Cryptic names
props:
max: 20
en: true

3. Provide Default Values

Always set sensible defaults in layout definitions:

propsSchema:
theme:
type: string
defaultValue: "auto" # ✅ Default provided

mode:
type: string
# ❌ No default - users must always specify

4. Document Your Props

Use description to explain prop purpose:

propsSchema:
maxContextDocs:
type: number
min: 1
max: 50
defaultValue: 10
description: "Maximum number of context documents to load. Higher values improve context but increase token usage." # ✅ Helpful

5. Use Type Constraints

Leverage oneOf, min, max to catch errors early:

propsSchema:
theme:
type: string
oneOf: ["light", "dark", "auto"] # ✅ Validates input
defaultValue: "auto"

# ❌ No constraint - any string accepted (prone to typos)
theme:
type: string
defaultValue: "auto"

6. Keep Layouts Focused

Each layout should serve a specific purpose:

# ✅ Good: Focused layouts
- crewx/default → Full agent profile with complete context
- crewx/minimal → Lightweight wrapper for simple agents

# ❌ Bad: One layout trying to do everything
- crewx/mega-layout → Supports 20 different modes with tons of props

7. Security Considerations

Never hardcode secrets:

# ❌ NEVER DO THIS
props:
apiKey: "sk-1234567890" # Hard-coded secret

Use environment variables instead:

# ✅ Reference environment variables in prompt
prompt: |
API Key: {{env.API_KEY}} # Safe: from environment

Trust only system layouts:

  • Built-in CrewX layouts are security-reviewed
  • Custom layouts should undergo security review
  • Props are sanitized and escaped by CrewX

Examples

Example 1: Simple Agent with Default Layout

Scenario: Create a basic code review agent.

agents:
- id: code_reviewer
name: "Code Review Assistant"
inline:
provider: "cli/claude"
layout: "crewx/default" # Use simple default
prompt: |
You are a code review assistant.

Review code for:
- Type safety
- Error handling
- Performance issues
- Security vulnerabilities

Provide constructive feedback with examples.

Usage:

crewx query "@code_reviewer review my authentication code"

Example 2: Minimal Agent for Simple Tasks

Scenario: Create a lightweight assistant for simple, focused tasks.

agents:
- id: quick_helper
name: "Quick Helper"
inline:
provider: "cli/claude"
layout: "crewx/minimal" # Lightweight wrapper
prompt: |
You are a quick helper for simple questions.

Keep answers:
- Concise and to the point
- Clear and actionable
- Under 3 sentences when possible

Focus on efficiency and speed.

Usage:

crewx query "@quick_helper what is the syntax for array map in JavaScript?"
crewx query "@quick_helper explain git rebase in one sentence"

Example 3: Multiple Agents Sharing Layout

Scenario: Create frontend and backend specialists sharing the same layout structure.

agents:
- id: frontend_specialist
name: "Frontend Expert"
inline:
provider: "cli/claude"
layout: "crewx/default" # Shared structure
prompt: |
You are a frontend development specialist.

Expertise:
- React, Vue, Angular
- CSS, Tailwind, styled-components
- Browser APIs and optimization

- id: backend_specialist
name: "Backend Expert"
inline:
provider: "cli/gemini"
layout: "crewx/default" # Same structure, different content
prompt: |
You are a backend development specialist.

Expertise:
- Node.js, Python, Go
- Database design (SQL, NoSQL)
- API design and security

Benefits:

  • Consistent prompt structure across agents
  • Easy to maintain (update layout once)
  • Clear separation of concerns

Example 4: Choosing Layout Based on Use Case

Scenario: Use different layouts for different complexity levels.

agents:
- id: simple_qa
name: "Simple Q&A Assistant"
inline:
layout: "crewx/minimal" # Lightweight for simple tasks
prompt: |
You are a Q&A assistant for quick questions.
Provide brief, direct answers without extra context.

- id: complex_analyst
name: "Complex Analysis Assistant"
inline:
layout: "crewx/default" # Full context for complex tasks
prompt: |
You are an analysis assistant for complex technical questions.

Provide comprehensive analysis including:
- Root cause investigation
- Multiple solution approaches
- Trade-off analysis
- Best practice recommendations

Use full context and agent capabilities as needed.

Example 5: Progressive Enhancement

Scenario: Start simple, optimize as needed.

Version 1: Start with implicit default

agents:
- id: assistant
inline:
# Implicit crewx/default layout
prompt: |
You are a helpful assistant.

Version 2: Make layout explicit

agents:
- id: assistant
inline:
layout: "crewx/default" # Explicit choice
prompt: |
You are a helpful assistant.

Version 3: Optimize for performance

agents:
- id: assistant
inline:
layout: "crewx/minimal" # Switch to minimal for efficiency
prompt: |
You are a helpful assistant focused on quick responses.

See Also

For Users:

For Developers: