Skip to main content

Overview

TriggerContext is a platform-agnostic struct that carries trigger metadata from any chat adapter (Discord, Teams, CLI) into the pipeline. It captures who triggered the task, from where, and includes the full conversation history for context.

Type Definition

pub struct TriggerContext {
    pub source: String,
    pub channel_id: String,
    pub user: String,
    pub message: String,
    pub chat_history: String,
}
source
String
Platform identifier (e.g., "discord", "teams", "cli")
channel_id
String
Channel or thread ID from the originating platform. For CLI, this is typically "local".
user
String
Username or identifier of the person who triggered the pipeline
message
String
The trigger message with @mention stripped. This is the raw task description.
chat_history
String
Full conversation history from the channel/thread. Used to provide context to the agent.

Methods

hydrate()

Populates a StepContext’s metadata HashMap with well-known keys from this trigger.
pub fn hydrate(&self, ctx: &mut StepContext)
ctx
&mut StepContext
required
The step context to populate with trigger metadata
Metadata Keys Populated:
  • "source" → platform identifier
  • "channel_id" → channel/thread ID
  • "user" → triggering user
  • "message" → task message (mention-stripped)
  • "chat_history" → conversation history
Example:
use magpie_core::{TriggerContext, StepContext};
use std::path::PathBuf;

let trigger = TriggerContext {
    source: "discord".to_string(),
    channel_id: "123456789".to_string(),
    user: "alice".to_string(),
    message: "fix login bug".to_string(),
    chat_history: "alice: the login is broken\nbob: what error do you see?".to_string(),
};

let mut ctx = StepContext::new(PathBuf::from("/repo"));
trigger.hydrate(&mut ctx);

// Metadata now contains all trigger fields
assert_eq!(ctx.metadata.get("source").unwrap(), "discord");
assert_eq!(ctx.metadata.get("user").unwrap(), "alice");

Usage in Pipeline

The pipeline creates a TriggerContext from the incoming request and passes it to blueprint execution:
// Discord adapter
let trigger = TriggerContext {
    source: "discord".to_string(),
    channel_id: thread_id.to_string(),
    user: author.name.clone(),
    message: stripped_content,
    chat_history: fetch_thread_history(thread_id).await?,
};

run_pipeline(&config, platform, &trigger).await?;
Inside blueprints, agent steps receive this context via StepContext.metadata:
let chat_history = ctx.metadata.get("chat_history").unwrap_or(&String::new());
let user = ctx.metadata.get("user").unwrap_or(&String::new());

let prompt = format!(
    "User {user} requested: {task}\n\nContext:\n{chat_history}"
);

Platform-Specific Examples

Discord

use magpie_core::TriggerContext;

let trigger = TriggerContext {
    source: "discord".to_string(),
    channel_id: message.channel_id.to_string(),
    user: message.author.name.clone(),
    message: content.trim_start_matches("<@123456>").trim().to_string(),
    chat_history: fetch_thread_messages(channel_id).await?,
};

Teams

use magpie_core::TriggerContext;

let trigger = TriggerContext {
    source: "teams".to_string(),
    channel_id: activity.conversation.id.clone(),
    user: activity.from.name.clone(),
    message: activity.text.replace("<at>magpie</at>", "").trim().to_string(),
    chat_history: fetch_conversation_history(&activity.conversation.id).await?,
};

CLI

use magpie_core::TriggerContext;

let trigger = TriggerContext {
    source: "cli".to_string(),
    channel_id: "local".to_string(),
    user: std::env::var("USER").unwrap_or_else(|_| "unknown".to_string()),
    message: task.clone(),
    chat_history: String::new(), // No conversation history for CLI
};

Design Rationale

Why Platform-Agnostic?

TriggerContext decouples the pipeline from platform-specific details:
  • Discord has threads, mentions, and snowflake IDs
  • Teams has conversations, activities, and AAD identities
  • CLI has none of these concepts
By abstracting to source, channel_id, user, message, and chat_history, the pipeline and blueprints work identically regardless of origin.

Why Include Chat History?

Chat history provides crucial context for the agent:
  • Requirements clarification: “alice: add OAuth → bob: which provider? → alice: Google”
  • Error details: Stack traces, screenshots, or error messages shared in the thread
  • Design decisions: “alice: use JWT → bob: 24hr expiry?”
Without history, the agent sees only the trigger message, missing important context.

ChatPlatform Trait

Implement custom chat adapters that produce TriggerContext

Pipeline API

How run_pipeline() consumes TriggerContext

Blueprint Types

How StepContext.metadata carries trigger data to agent steps

Discord Adapter

Real-world example of TriggerContext creation

Build docs developers (and LLMs) love