| name | fundamentals |
| description | Core langchainx patterns — LLMChain, builder pattern, Chain trait, prompt macros, and basic invocation. |
Build chains with LLMChainBuilder, use prompt_args! for input, call chain.invoke() or
chain.call() for output. The builder pattern is universal across all chain types.
## Builder Pattern
Every chain type uses a *Builder struct with method chaining and a .build() that returns
Result<Chain, ChainError>. Required fields cause a ChainError::MissingObject if absent.
let chain = LLMChainBuilder::new()
.prompt(formatter)
.llm(llm)
.options(ChainCallOptions::default())
.output_key("answer")
.build()?;
## Prompt Macros
use langchainx::{
message_formatter, fmt_message, fmt_template,
prompt::{HumanMessagePromptTemplate, MessageOrTemplate},
prompt_args, template_fstring,
schemas::Message,
};
let prompt = message_formatter![
fmt_message!(Message::new_system_message("You are a helpful assistant.")),
fmt_template!(HumanMessagePromptTemplate::new(
template_fstring!("{input}", "input")
)),
];
let input = prompt_args! {
"input" => "What is Rust?",
};
## LLMChain — Basic Usage
use langchainx::{
chain::{Chain, LLMChainBuilder},
llm::openai::OpenAI,
message_formatter, fmt_message, fmt_template,
prompt::{HumanMessagePromptTemplate, MessageOrTemplate},
prompt_args, template_fstring,
schemas::Message,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let llm = OpenAI::default();
let prompt = message_formatter![
fmt_message!(Message::new_system_message("You are helpful.")),
fmt_template!(HumanMessagePromptTemplate::new(
template_fstring!("{input}", "input")
)),
];
let chain = LLMChainBuilder::new()
.prompt(prompt)
.llm(llm)
.build()?;
let output = chain.invoke(prompt_args! { "input" => "Hello" }).await?;
println!("{output}");
let result = chain.call(prompt_args! { "input" => "Hello" }).await?;
println!("{}", result.generation);
println!("{:?}", result.tokens);
Ok(())
}
## Chain Trait
#[async_trait]
pub trait Chain: Sync + Send {
async fn call(&self, input_variables: PromptArgs) -> Result<GenerateResult, ChainError>;
async fn invoke(&self, input_variables: PromptArgs) -> Result<String, ChainError>;
async fn execute(&self, input_variables: PromptArgs) -> Result<HashMap<String, Value>, ChainError>;
async fn stream(&self, input_variables: PromptArgs)
-> Result<Pin<Box<dyn Stream<Item = Result<StreamData, ChainError>> + Send>>, ChainError>;
fn get_input_keys(&self) -> Vec<String>;
fn get_output_keys(&self) -> Vec<String>;
}
invoke — returns just the generated string (most common)
call — returns GenerateResult with token usage
execute — returns HashMap<String, Value> keyed by output key
stream — returns a Stream of StreamData chunks
## Common Mistake: Missing prompt variables
prompt_args! keys must exactly match the variable names in template_fstring!.
let prompt = message_formatter![fmt_template!(
HumanMessagePromptTemplate::new(template_fstring!("{input}", "input"))
)];
let args = prompt_args! { "query" => "Hello" };
let args = prompt_args! { "input" => "Hello" };