Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:

jobs:
format:
name: Check formatting
runs-on: ubuntu-latest
env:
UV_FROZEN: "true"
RUFF_OUTPUT_FORMAT: github
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-suffix: "format"
python-version: "3.13"

- name: Install dependencies
run: uv sync --group lint

- name: Check formatting with ruff
run: uv run --group lint ruff format . --check

lint:
name: Lint code
runs-on: ubuntu-latest
env:
UV_FROZEN: "true"
RUFF_OUTPUT_FORMAT: github
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-suffix: "lint"
python-version: "3.13"

- name: Install dependencies
run: uv sync --group lint

- name: Lint with ruff
run: uv run --group lint ruff check .

typecheck:
name: Type check
runs-on: ubuntu-latest
env:
UV_FROZEN: "true"
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-suffix: "typing"
python-version: "3.13"

- name: Install dependencies
run: uv sync --group typing

- name: Type check with ty
run: uv run --group typing ty check src/deepagents

test:
name: Test Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
env:
UV_FROZEN: "true"
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-suffix: "test-py${{ matrix.python-version }}"
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --group test

- name: Run tests
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: uv run --group test pytest tests/ -v --cov=deepagents --cov-report=xml --cov-report=term

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
fail_ci_if_error: false
121 changes: 121 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Release

on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.2.1)'
required: true
type: string

jobs:
build:
name: Build distribution
runs-on: ubuntu-latest
outputs:
package-version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Get package version
id: get-version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
else
# Extract version from pyproject.toml
VERSION=$(grep -E '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
echo "version=$VERSION" >> $GITHUB_OUTPUT
fi

- name: Build package
run: uv build

- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: Publish to PyPI
needs: [build]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/deepagents
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

test-release:
name: Test PyPI Release
needs: [build]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
permissions:
id-token: write

steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Publish distribution to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true

github-release:
name: Create GitHub Release
needs: [build, publish-to-pypi]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
permissions:
contents: write

steps:
- uses: actions/checkout@v4

- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
VERSION="${{ needs.build.outputs.package-version }}"

gh release create \
"v${VERSION}" \
--repo '${{ github.repository }}' \
--title "v${VERSION}" \
--generate-notes \
dist/*
14 changes: 8 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
PYTHON_FILES=.
MYPY_CACHE=.mypy_cache
lint format: PYTHON_FILES=.
lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=src/deepagents --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$')
lint_package: PYTHON_FILES=src/deepagents
lint_tests: PYTHON_FILES=tests

lint lint_diff lint_package lint_tests:
[ "$(PYTHON_FILES)" = "" ] || uv run --all-groups ruff check $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || uv run --all-groups ruff format $(PYTHON_FILES) --diff
[ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) && uv run --all-groups mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE)
[ "$(PYTHON_FILES)" = "" ] || uv run --group lint ruff check $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || uv run --group lint ruff format $(PYTHON_FILES) --check
[ "$(PYTHON_FILES)" = "" ] || uv run --group typing ty check $(PYTHON_FILES)

format format_diff:
[ "$(PYTHON_FILES)" = "" ] || uv run --all-groups ruff format $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || uv run --all-groups ruff check --fix $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || uv run --group lint ruff format $(PYTHON_FILES)
[ "$(PYTHON_FILES)" = "" ] || uv run --group lint ruff check --fix $(PYTHON_FILES)

test:
uv run --group test pytest tests/ -v
9 changes: 4 additions & 5 deletions examples/research/research_agent.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from typing import Literal

from tavily import TavilyClient
from tavily import TavilyClient # type: ignore[import-untyped]

from deepagents import create_deep_agent

Expand All @@ -16,14 +16,13 @@ def internet_search(
topic: Literal["general", "news", "finance"] = "general",
include_raw_content: bool = False,
):
"""Run a web search"""
search_docs = tavily_client.search(
"""Run a web search."""
return tavily_client.search(
query,
max_results=max_results,
include_raw_content=include_raw_content,
topic=topic,
)
return search_docs


sub_research_prompt = """You are a dedicated researcher. Your job is to conduct research based on the users questions.
Expand Down Expand Up @@ -128,7 +127,7 @@ def internet_search(
For each section of the report, do the following:
- Use simple, clear language
- Use ## for section title (Markdown format) for each section of the report
- Do NOT ever refer to yourself as the writer of the report. This should be a professional report without any self-referential language.
- Do NOT ever refer to yourself as the writer of the report. This should be a professional report without any self-referential language.
- Do not say what you are doing in the report. Just write the report without any commentary from yourself.
- Each section should be as long as necessary to deeply answer the question with the information you have gathered. It is expected that sections will be fairly long and verbose. You are writing a deep research report, and users will expect a thorough answer.
- Use bullet points to list out information when appropriate, but by default, write in paragraph form.
Expand Down
52 changes: 26 additions & 26 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,33 @@ dependencies = [
"wcmatch"
]

[project.optional-dependencies]
dev = [
[dependency-groups]
test = [
"pytest",
"pytest-cov",
"build",
"twine",
"langchain-openai",
]

[dependency-groups]
lint = [
"ruff>=0.12.2,<0.13.0",
]
typing = [
"mypy>=1.18.1,<1.19.0",
"ty",
]
dev = [
{ include-group = "test" },
{ include-group = "lint" },
{ include-group = "typing" },
]

[build-system]
requires = ["setuptools>=73.0.0", "wheel"]
build-backend = "setuptools.build_meta"
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.setuptools]
[tool.setuptools.packages.find]
where = ["src"]
include = ["deepagents*"]
[tool.hatch.build.targets.wheel]
packages = ["src/deepagents"]

[tool.setuptools.package-dir]
"" = "src"

[tool.setuptools.package-data]
"*" = ["py.typed"]
[tool.hatch.build.targets.wheel.force-include]
"src/deepagents/py.typed" = "deepagents/py.typed"

[tool.ruff]
line-length = 150
Expand All @@ -65,6 +61,9 @@ ignore = [
"PLR0913", # Too many arguments in function definition
"PLC0414", # Inconsistent with how type checkers expect to be notified of intentional re-exports
"C901", # Too complex
"PLR2004", # Magic values in comparisons (common in tests)
"DTZ", # Datetime without timezone (not always needed)
"FBT", # Boolean positional arguments (common pattern)
]
unfixable = ["B028"] # Rules that shouldn't be auto-fixed

Expand All @@ -83,13 +82,14 @@ ignore-var-parameters = true
"D1", # Skip documentation rules in tests
"S101", # Allow asserts in tests
"S311", # Allow pseudo-random generators in tests
# Add more test-specific ignores
"ANN", # Skip type annotations in tests
"RUF012", # Allow mutable class attributes in tests
]
"examples/*" = [
"D", # Skip documentation rules in examples
"INP001", # Examples don't need __init__.py
"E501", # Allow longer lines in examples
"FBT", # Allow boolean positional arguments in examples
"ANN", # Skip type annotations in examples
]

[tool.mypy]
strict = true
ignore_missing_imports = true
enable_error_code = ["deprecated"]
# Optional: reduce strictness if needed
disallow_any_generics = false
warn_return_any = false
2 changes: 1 addition & 1 deletion src/deepagents/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from deepagents.backends.composite import CompositeBackend
from deepagents.backends.filesystem import FilesystemBackend
from deepagents.backends.protocol import BackendProtocol
from deepagents.backends.state import StateBackend
from deepagents.backends.store import StoreBackend
from deepagents.backends.protocol import BackendProtocol

__all__ = [
"BackendProtocol",
Expand Down
Loading
Loading