Skip to main content

Basic LangChain agent with tracing

# agent.py
import langship
from langchain.agents import initialize_agent, load_tools
from langchain.llms import OpenAI

langship.init(
    endpoint="https://langship.yourcompany.com",
    api_key="your-api-key",
    project="support-agent",
    environment="production"
)

llm = OpenAI(temperature=0, model="gpt-4o")
tools = load_tools(["serpapi", "calculator"], llm=llm)
agent = initialize_agent(tools, llm, verbose=False)

response = agent.run("What's 15% of the revenue from Q3 2024?")
print(response)
Every LLM call and tool invocation is automatically traced. No additional code needed.

Customer support bot eval pipeline

langship.yaml:
project: support-agent

datasets:
  support-cases:
    path: ./evals/support-cases.jsonl

evals:
  - name: correct-resolution
    type: llm-judge
    model: gpt-4o
    prompt: |
      Did this support response correctly resolve the customer's issue?
      Issue: {{input}}
      Response: {{output}}
      Score 1 if resolved, 0 if not.
    dataset: support-cases
    pass_threshold: 0.85
    blocking: true

  - name: tone-check
    type: llm-judge
    model: gpt-4o-mini
    prompt: |
      Is this response professional and empathetic?
      Response: {{output}}
      Score 0 to 1.
    dataset: support-cases
    pass_threshold: 0.9
    blocking: false

  - name: no-pii-leak
    type: regex
    pattern: "\\b\\d{3}-\\d{2}-\\d{4}\\b"  # SSN pattern
    negate: true      # fail if SSN is found in output
    dataset: support-cases
    blocking: true

deployments:
  staging:
    target: lyzr
    agent_id: ${STAGING_AGENT_ID}
    on_pass: true
    branches: [main]
evals/support-cases.jsonl:
{"input": "My order hasn't arrived after 2 weeks", "expected_theme": "apology + tracking + escalation"}
{"input": "I want to cancel my subscription", "expected_theme": "retention offer + cancellation confirmation"}
{"input": "How do I reset my password?", "expected_theme": "step-by-step reset instructions"}

RAG agent with retrieval quality tracking

import langship
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA

langship.init(project="rag-agent", environment="production")

vectorstore = Chroma(embedding_function=OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)

def answer_question(question: str) -> str:
    with langship.span("retrieval", input={"question": question}) as span:
        docs = retriever.get_relevant_documents(question)
        span.set_attribute("num_docs_retrieved", len(docs))
        span.set_attribute("top_doc_score", docs[0].metadata.get("score"))
        span.set_output({"docs": [d.page_content[:200] for d in docs]})

    return qa_chain.run(question)
Adding a manual retrieval span lets you track retrieval quality separately from generation quality in the Control Plane dashboard.

Multi-agent pipeline

import langship

langship.init(project="research-pipeline")

def research_agent(topic: str) -> str:
    with langship.span("research-agent", input={"topic": topic}) as span:
        # ... calls web search tools ...
        result = run_research(topic)
        span.set_output({"summary": result})
        return result

def writer_agent(research: str) -> str:
    with langship.span("writer-agent", input={"research": research}) as span:
        # ... calls LLM to write article ...
        article = write_article(research)
        span.set_output({"article": article})
        return article

def editor_agent(article: str) -> str:
    with langship.span("editor-agent", input={"article": article}) as span:
        edited = edit_article(article)
        span.set_output({"edited": edited})
        return edited

# The trace shows all three agents as siblings under the run root
research = research_agent("quantum computing breakthroughs 2024")
draft = writer_agent(research)
final = editor_agent(draft)

GitHub Actions: eval on PR + deploy on merge

# .github/workflows/agent-ci.yml
name: Agent CI/CD

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  eval:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}

      - run: pip install -r requirements.txt

      - name: Run evals
        uses: langship/eval-action@v1
        with:
          api-key: ${{ secrets.LANGSHIP_API_KEY }}
          url: ${{ secrets.LANGSHIP_URL }}
          fail-on-regression: true
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

  deploy-staging:
    needs: eval
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - run: pip install langship
      - name: Deploy to staging
        run: langship deploy --env staging --agent-id ${{ vars.STAGING_AGENT_ID }}
        env:
          LANGSHIP_API_KEY: ${{ secrets.LANGSHIP_API_KEY }}
          LANGSHIP_ENDPOINT: ${{ secrets.LANGSHIP_URL }}

Cost monitoring alert

Set a daily cost budget alert via the Control Plane API:
import httpx

httpx.post(
    "https://langship.yourcompany.com/api/alerts",
    headers={"Authorization": f"Bearer {api_key}"},
    json={
        "project": "support-agent",
        "metric": "daily_cost_usd",
        "threshold": 50.0,
        "operator": "gt",
        "channel": {
            "type": "slack",
            "webhook_url": "https://hooks.slack.com/..."
        }
    }
)
Or configure in langship.yaml:
alerts:
  - name: daily-cost-budget
    metric: daily_cost_usd
    threshold: 50.0
    operator: gt
    channel:
      type: slack
      webhook_url: ${SLACK_WEBHOOK}