Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Design LLM applications using the LangChain framework with agents, memory, and tool integration patterns. Use when building LangChain applications, implementing AI agents, or creating complex LLM workflows.
.claude/skills/microck-langchain-architecture/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 225% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 101% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 83% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 200% | 0% |
| case-22 | ✓→✓ | = Same ✓ | 114% | 0% |
Master the LangChain framework for building sophisticated LLM applications with agents, chains, memory, and tool integration.
Autonomous systems that use LLMs to decide which actions to take.
Agent Types:
Sequences of calls to LLMs or other utilities.
Chain Types:
Systems for maintaining context across interactions.
Memory Types:
Loading, transforming, and storing documents for retrieval.
Components:
Hooks for logging, monitoring, and debugging.
Use Cases:
pythonfrom langchain.agents import AgentType, initialize_agent, load_tools from langchain.llms import OpenAI from langchain.memory import ConversationBufferMemory # Initialize LLM llm = OpenAI(temperature=0) # Load tools tools = load_tools(["serpapi", "llm-math"], llm=llm) # Add memory memory = ConversationBufferMemory(memory_key="chat_history") # Create agent agent = initialize_agent( tools, llm, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, memory=memory, verbose=True ) # Run agent result = agent.run("What's the weather in SF? Then calculate 25 * 4")
pythonfrom langchain.chains import RetrievalQA from langchain.document_loaders import TextLoader from langchain.text_splitter import CharacterTextSplitter from langchain.vectorstores import Chroma from langchain.embeddings import OpenAIEmbeddings # Load and process documents loader = TextLoader('documents.txt') documents = loader.load() text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200) texts = text_splitter.split_documents(documents) # Create vector store embeddings = OpenAIEmbeddings() vectorstore = Chroma.from_documents(texts, embeddings) # Create retrieval chain qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever(), return_source_documents=True ) # Query result = qa_chain({"query": "What is the main topic?"})
pythonfrom langchain.agents import Tool, AgentExecutor from langchain.agents.react.base import ReActDocstoreAgent from langchain.tools import tool @tool def search_database(query: str) -> str: """Search internal database for information.""" # Your database search logic return f"Results for: {query}" @tool def send_email(recipient: str, content: str) -> str: """Send an email to specified recipient.""" # Email sending logic return f"Email sent to {recipient}" tools = [search_database, send_email] agent = initialize_agent( tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True )
pythonfrom langchain.chains import LLMChain, SequentialChain from langchain.prompts import PromptTemplate # Step 1: Extract key information extract_prompt = PromptTemplate( input_variables=["text"], template="Extract key entities from: {text}\n\nEntities:" ) extract_chain = LLMChain(llm=llm, prompt=extract_prompt, output_key="entities") # Step 2: Analyze entities analyze_prompt = PromptTemplate( input_variables=["entities"], template="Analyze these entities: {entities}\n\nAnalysis:" ) analyze_chain = LLMChain(llm=llm, prompt=analyze_prompt, output_key="analysis") # Step 3: Generate summary summary_prompt = PromptTemplate( input_variables=["entities", "analysis"], template="Summarize:\nEntities: {entities}\nAnalysis: {analysis}\n\nSummary:" ) summary_chain = LLMChain(llm=llm, prompt=summary_prompt, output_key="summary") # Combine into sequential chain overall_chain = SequentialChain( chains=[extract_chain, analyze_chain, summary_chain], input_variables=["text"], output_variables=["entities", "analysis", "summary"], verbose=True )
python# For short conversations (< 10 messages) from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory() # For long conversations (summarize old messages) from langchain.memory import ConversationSummaryMemory memory = ConversationSummaryMemory(llm=llm) # For sliding window (last N messages) from langchain.memory import ConversationBufferWindowMemory memory = ConversationBufferWindowMemory(k=5) # For entity tracking from langchain.memory import ConversationEntityMemory memory = ConversationEntityMemory(llm=llm) # For semantic retrieval of relevant history from langchain.memory import VectorStoreRetrieverMemory memory = VectorStoreRetrieverMemory(retriever=retriever)
pythonfrom langchain.callbacks.base import BaseCallbackHandler class CustomCallbackHandler(BaseCallbackHandler): def on_llm_start(self, serialized, prompts, **kwargs): print(f"LLM started with prompts: {prompts}") def on_llm_end(self, response, **kwargs): print(f"LLM ended with response: {response}") def on_llm_error(self, error, **kwargs): print(f"LLM error: {error}") def on_chain_start(self, serialized, inputs, **kwargs): print(f"Chain started with inputs: {inputs}") def on_agent_action(self, action, **kwargs): print(f"Agent taking action: {action}") # Use callback agent.run("query", callbacks=[CustomCallbackHandler()])
pythonimport pytest from unittest.mock import Mock def test_agent_tool_selection(): # Mock LLM to return specific tool selection mock_llm = Mock() mock_llm.predict.return_value = "Action: search_database\nAction Input: test query" agent = initialize_agent(tools, mock_llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION) result = agent.run("test query") # Verify correct tool was selected assert "search_database" in str(mock_llm.predict.call_args) def test_memory_persistence(): memory = ConversationBufferMemory() memory.save_context({"input": "Hi"}, {"output": "Hello!"}) assert "Hi" in memory.load_memory_variables({})['history'] assert "Hello!" in memory.load_memory_variables({})['history']
pythonfrom langchain.cache import InMemoryCache import langchain langchain.llm_cache = InMemoryCache()
python# Process multiple documents in parallel from langchain.document_loaders import DirectoryLoader from concurrent.futures import ThreadPoolExecutor loader = DirectoryLoader('./docs') docs = loader.load() def process_doc(doc): return text_splitter.split_documents([doc]) with ThreadPoolExecutor(max_workers=4) as executor: split_docs = list(executor.map(process_doc, docs))
pythonfrom langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler llm = OpenAI(streaming=True, callbacks=[StreamingStdOutCallbackHandler()])
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 12,248 | 11,074 | -10% | 1 | 1 | 0% | 2,429 | 4,441 | +83% | 0 | 0 | — |
case-02 | pass→pass | 6,871 | 6,836 | -1% | 1 | 1 | 0% | 1,173 | 3,524 | +200% | 0 | 0 | — |
case-03 | fail→pass | 6,542 | 5,446 | -17% | 1 | 1 | 0% | 1,057 | 3,440 | +225% | 0 | 0 | — |
case-22 | pass→pass | 9,656 | 8,711 | -10% | 1 | 1 | 0% | 1,998 | 4,280 | +114% | 0 | 0 | — |
case-04 | pass→pass | 10,055 | 5,217 | -48% | 1 | 1 | 0% | 1,025 | 3,295 | +221% | 0 | 0 | — |
case-05 | pass→pass | 6,640 | 4,910 | -26% | 1 | 1 | 0% | 1,164 | 3,238 | +178% | 0 | 0 | — |
case-06 | pass→pass | 13,968 | 11,498 | -18% | 1 | 1 | 0% | 2,623 | 4,657 | +78% | 0 | 0 | — |
case-07 | pass→pass | 9,760 | 6,216 | -36% | 1 | 1 | 0% | 1,779 | 3,459 | +94% | 0 | 0 | — |
case-08 | pass→pass | 3,876 | 3,907 | +1% | 1 | 1 | 0% | 696 | 3,094 | +345% | 0 | 0 | — |
case-09 | pass→pass | 7,586 | 6,330 | -17% | 1 | 1 | 0% | 1,595 | 3,616 | +127% | 0 | 0 | — |
case-10 | pass→pass | 8,040 | 7,772 | -3% | 1 | 1 | 0% | 1,480 | 3,733 | +152% | 0 | 0 | — |
case-11 | fail→fail | 15,942 | 13,840 | -13% | 1 | 1 | 0% | 3,180 | 5,113 | +61% | 0 | 0 | — |
case-12 | pass→pass | 11,375 | 10,459 | -8% | 1 | 1 | 0% | 2,033 | 4,385 | +116% | 0 | 0 | — |
case-13 | pass→pass | 5,384 | 3,742 | -30% | 1 | 1 | 0% | 928 | 3,049 | +229% | 0 | 0 | — |
case-14 | pass→pass | 12,006 | 7,856 | -35% | 1 | 1 | 0% | 2,067 | 3,814 | +85% | 0 | 0 | — |
case-15 | pass→pass | 2,428 | 3,050 | +26% | 1 | 1 | 0% | 413 | 2,933 | +610% | 0 | 0 | — |
case-16 | fail→fail | 13,927 | 13,763 | -1% | 1 | 1 | 0% | 2,326 | 4,905 | +111% | 0 | 0 | — |
case-17 | fail→pass | 12,659 | 9,958 | -21% | 1 | 1 | 0% | 2,182 | 4,382 | +101% | 0 | 0 | — |
case-18 | pass→pass | 6,428 | 8,556 | +33% | 1 | 1 | 0% | 1,118 | 4,040 | +261% | 0 | 0 | — |
case-19 | pass→pass | 4,020 | 5,739 | +43% | 1 | 1 | 0% | 841 | 3,504 | +317% | 0 | 0 | — |
case-20 | pass→pass | 6,449 | 4,923 | -24% | 1 | 1 | 0% | 991 | 3,408 | +244% | 0 | 0 | — |
case-21 | pass→pass | 3,906 | 3,913 | +0% | 1 | 1 | 0% | 617 | 3,100 | +402% | 0 | 0 | — |
case-23 | pass→pass | 4,945 | 5,023 | +2% | 1 | 1 | 0% | 922 | 3,233 | +251% | 0 | 0 | — |
case-24 | pass→pass | 7,157 | 6,590 | -8% | 1 | 1 | 0% | 1,431 | 3,671 | +157% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +8 percentage points is the difference between those two pass rates over the 24 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.