diff --git a/.github/actions/run-adk-agent/README.md b/.github/actions/run-adk-agent/README.md new file mode 100644 index 0000000..235a4a8 --- /dev/null +++ b/.github/actions/run-adk-agent/README.md @@ -0,0 +1,47 @@ +# Run ADK Agent + +A reusable GitHub Action that runs `gradient agent run` to validate an ADK agent starts and is available at http://localhost:8080. + +## Usage + +```yaml +- uses: actions/checkout@v4 +- uses: ./.github/actions/run-adk-agent + with: + working-directory: WebSearch + digitalocean-inference-key: ${{ secrets.DIGITALOCEAN_INFERENCE_KEY }} +``` + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `working-directory` | Yes | - | Path to agent directory (e.g., WebSearch, StateGraph, RAG) | +| `digitalocean-inference-key` | Yes | - | DigitalOcean GenAI inference key for LLM calls | +| `python-version` | No | `3.10` | Python version | +| `openai-api-key` | No | - | OpenAI API key (for RAG embeddings; not needed for WebSearch) | + +## Secrets Setup + +Add the required secret in your GitHub repo before the workflow can run: + +1. Go to your repo on GitHub → **Settings** → **Secrets and variables** → **Actions** +2. Click **New repository secret** +3. Name: `DIGITALOCEAN_INFERENCE_KEY` +4. Value: Your DigitalOcean GenAI inference key (from [GenAI Settings](https://cloud.digitalocean.com/gen-ai)) +5. Click **Add secret** + +The secret is stored encrypted by GitHub and never shown in logs or to contributors. + +## Secrets by Template + +| Template | Required | Optional | +|----------|----------|----------| +| WebSearch | `DIGITALOCEAN_INFERENCE_KEY` | - | +| StateGraph | `DIGITALOCEAN_INFERENCE_KEY` | - | +| RAG | `DIGITALOCEAN_INFERENCE_KEY` | `OPENAI_API_KEY` | +| Others | See template `.env.example` | - | + +## GitHub Enterprise + +Works on GitHub.com and GitHub Enterprise Server. Uses standard `actions/checkout` and `actions/setup-python`. diff --git a/.github/actions/run-adk-agent/action.yml b/.github/actions/run-adk-agent/action.yml new file mode 100644 index 0000000..b334003 --- /dev/null +++ b/.github/actions/run-adk-agent/action.yml @@ -0,0 +1,39 @@ +name: 'Run ADK Agent' +description: 'Run gradient agent run to validate agent starts and is available at http://localhost:8080' +inputs: + working-directory: + required: true + description: 'Path to agent directory (e.g., WebSearch, StateGraph)' + digitalocean-inference-key: + required: true + description: 'DigitalOcean inference key (for LLM)' + python-version: + required: false + default: '3.10' + openai-api-key: + required: false + description: 'OpenAI API key (for RAG embeddings; not needed for WebSearch)' +runs: + using: composite + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + - run: pip install gradient-adk + shell: bash + - run: pip install -r requirements.txt + working-directory: ${{ inputs.working-directory }} + shell: bash + - run: | + gradient agent run & + for i in $(seq 1 30); do + curl -s -o /dev/null --connect-timeout 2 http://127.0.0.1:8080/ && { echo "Port 8080 is listening"; exit 0; } + sleep 2 + done + echo "Agent failed to start within 60 seconds" + exit 1 + working-directory: ${{ inputs.working-directory }} + shell: bash + env: + DIGITALOCEAN_INFERENCE_KEY: ${{ inputs.digitalocean-inference-key }} + OPENAI_API_KEY: ${{ inputs.openai-api-key }} diff --git a/.github/workflows/validate-websearch.yml b/.github/workflows/validate-websearch.yml new file mode 100644 index 0000000..a710650 --- /dev/null +++ b/.github/workflows/validate-websearch.yml @@ -0,0 +1,13 @@ +on: + pull_request: + paths: ['WebSearch/**'] + workflow_dispatch: +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/run-adk-agent + with: + working-directory: WebSearch + digitalocean-inference-key: ${{ secrets.DIGITALOCEAN_INFERENCE_KEY }} diff --git a/WebSearch/main.py b/WebSearch/main.py index 5a8271f..804ac9c 100644 --- a/WebSearch/main.py +++ b/WebSearch/main.py @@ -1,9 +1,10 @@ import os from gradient_adk import entrypoint from langchain_core.tools import tool +from langchain_core.prompts import ChatPromptTemplate from langchain_gradient import ChatGradient from langchain_core.messages import HumanMessage -from langchain.agents import create_agent +from langgraph.prebuilt import create_react_agent from pydantic import BaseModel from langchain_community.tools import DuckDuckGoSearchRun @@ -25,9 +26,12 @@ def web_search(query: str) -> str: model="openai-gpt-oss-120b", ) -agent = create_agent( - llm, tools=[web_search], system_prompt=SYSTEM_PROMPT -) +prompt = ChatPromptTemplate.from_messages([ + ("system", SYSTEM_PROMPT), + ("placeholder", "{messages}"), +]) + +agent = create_react_agent(model=llm, tools=[web_search], prompt=prompt) class Message(BaseModel): diff --git a/WebSearch/requirements.txt b/WebSearch/requirements.txt index 87c62ab..9b38283 100644 --- a/WebSearch/requirements.txt +++ b/WebSearch/requirements.txt @@ -1,8 +1,8 @@ gradient-adk -langchain==1.0.0 -langchain-core==1.2.11 -langchain-community -langgraph==1.0.0 -langchain-gradient>=0.1.0 +langchain>=0.3.0,<0.4.0 +langchain-core>=0.3.15,<0.4.0 +langchain-community>=0.3.0 +langgraph +langchain-gradient pydantic>=2.6,<3 ddgs