Skip to content

Commit e355c05

Browse files
authored
Merge pull request #72 from docker/sock-store
Sock store Demo
2 parents ef34693 + cf3762e commit e355c05

33 files changed

+3776
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
**/.DS_Store
2+
**/.direnv/
3+
/.vscode/
4+
/.cursor/
5+
**/init-secrets.sh
6+
**/secret.openai-api-key

adk-sock-shop/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*
2+
!/agents
3+
!/apps
4+
!/docker
5+
!/pyproject.toml
6+
!/uv.lock

adk-sock-shop/.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use nix

adk-sock-shop/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/.vscode
2+
/.venv
3+
/.mypy_cache
4+
/.pytest_cache
5+
/.ruff_cache
6+
/.python-version
7+
**/__pycache__/
8+
.mcp.env

adk-sock-shop/.mcp.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
brave.api_key=<fill-me>
2+
mongodb.connection_string=mongodb://<user>:<password>@mongodb:27017/sockstore

adk-sock-shop/.ruff.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[lint]
2+
select = ["E4", "E7", "E9", "F", "I", "RUF022"]
3+
4+
[lint.isort]
5+
force-sort-within-sections = true

adk-sock-shop/CLAUDE.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Development Commands
6+
7+
### Build and Run
8+
```bash
9+
# Build and push multi-platform image (requires hydrobuild builder)
10+
make build-adk-image
11+
```
12+
13+
### Development Tools
14+
```bash
15+
# Type checking
16+
pyright
17+
18+
# Code formatting and linting
19+
ruff check
20+
ruff format
21+
```
22+
23+
### Testing and Development
24+
- Access the web interface at `http://localhost:8080` after running `docker compose up --build`
25+
- Use Google Cloud Run deployment with `compose.gcloudrun.yaml` for cloud deployment
26+
27+
## Architecture Overview
28+
29+
This is an **ADK (Agent Development Kit) multi-agent fact-checking system** with three coordinated agents:
30+
31+
### Agent Hierarchy
32+
- **Root Agent**: `llm_auditor` (SequentialAgent) at `agents/agent.py:22`
33+
- Orchestrates the entire fact-checking workflow
34+
- Coordinates between Critic and Reviser agents sequentially
35+
36+
- **Critic Agent**: `agents/sub_agents/critic/agent.py:27`
37+
- Has access to DuckDuckGo search via MCP (Model Context Protocol)
38+
- Gathers external evidence to support or refute claims
39+
- Uses `mcp/duckduckgo:search` toolset
40+
41+
- **Reviser Agent**: `agents/sub_agents/reviser/agent.py:97`
42+
- No external tools - pure reasoning agent
43+
- Refines conclusions based on Critic's findings
44+
- Uses content processing callbacks for model compatibility
45+
46+
### Agent Communication Pattern
47+
1. User submits question → Auditor
48+
2. Auditor → Critic (with search tools)
49+
3. Critic gathers evidence → Auditor
50+
4. Auditor → Reviser (reasoning only)
51+
5. Reviser refines conclusion → Auditor
52+
6. Auditor delivers final answer
53+
54+
### Special Implementation Notes
55+
- Reviser agent uses content preprocessing callbacks (`force_string_content`, `_remove_end_of_edit_mark`) for model compatibility
56+
- MCP tools are configured via `create_mcp_toolsets()` in critic agent
57+
- All agents use LiteLLM for model abstraction with OpenAI format
58+
59+
### Generating a compose.yaml file
60+
61+
* To add models and gateways to an existing compose.yaml file, you should figure out which model you want to use, and which mcp servers are needed.
62+
* Create a service entry like the following
63+
```
64+
mcp-gateway:
65+
image: docker/mcp-gateway:latest
66+
use_api_socket: true
67+
command:
68+
- --transport=sse
69+
- --servers=server1,server2,server3
70+
- --config=/mcp_config
71+
- --secrets=docker-desktop:/run/secrets/mcp_secret
72+
secrets:
73+
- mcp_secret
74+
```
75+
but replace the servers value with a comma-separate list of the MCP servers that you want to use.
76+
* Also, if there is no top-level `secrets` entry with a `mcp_secret` entry then add one. It should look like:
77+
```
78+
secrets:
79+
mcp_secret:
80+
file: ./.mcp.env
81+
```
82+
and remind that the user that Docker offload will require secrets to be stored in a local file named .mcp.env
83+
* Whenever a model is needed, add a toplevel entry in the compose.yaml file with the name of the model. It should look like:
84+
```
85+
models:
86+
<model_name>:
87+
model: <model_image_ref>
88+
```
89+
but replace the <model_name> with whatever model the user wants to use.
90+
If the user wnts the model_name qwen3 then the model_image_ref should be ai/qwen3:14B-Q6_K
91+
* whenever a model is added, the user must specify what service needs the model.
92+
Add a new entry to that service's definition with the following content.
93+
94+
```
95+
models:
96+
<model_name>:
97+
endpoint_var: MODEL_RUNNER_URL
98+
model_var: MODEL_RUNNER_MODEL
99+
```
100+
If it's unclear which service needs this definition then ask. Always add the model to just the service definition that needs it.

adk-sock-shop/Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Use Python 3.11 slim image as base
2+
FROM python:3.13-slim
3+
ENV PYTHONUNBUFFERED=1
4+
5+
RUN pip install uv
6+
7+
WORKDIR /app
8+
# Install system dependencies
9+
COPY pyproject.toml uv.lock ./
10+
RUN --mount=type=cache,target=/root/.cache/uv \
11+
UV_COMPILE_BYTECODE=1 uv pip install --system .
12+
# Copy application code
13+
COPY agents/ ./agents/
14+
RUN python -m compileall -q .
15+
16+
COPY <<EOF /entrypoint.sh
17+
#!/bin/sh
18+
set -e
19+
20+
# if test -f /run/secrets/openai-api-key; then
21+
# export OPENAI_API_KEY=$(cat /run/secrets/openai-api-key)
22+
# fi
23+
24+
# if test -n "\${OPENAI_API_KEY}"; then
25+
# echo "Using OpenAI with \${OPENAI_MODEL_NAME}"
26+
# else
27+
echo "Using Docker Model Runner with \${MODEL_RUNNER_MODEL}"
28+
export OPENAI_MODEL_NAME=openai/\${MODEL_RUNNER_MODEL}
29+
# fi
30+
exec adk api_server --host 0.0.0.0 --port 8000 --log_level DEBUG
31+
EOF
32+
RUN chmod +x /entrypoint.sh
33+
34+
# Create non-root user
35+
RUN useradd --create-home --shell /bin/bash app \
36+
&& chown -R app:app /app
37+
USER app
38+
39+
ENTRYPOINT [ "/entrypoint.sh" ]

adk-sock-shop/Dockerfile.adk-ui

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
# Use Python 3.11 slim image as base
3+
FROM python:3.13-slim
4+
ENV PYTHONUNBUFFERED=1
5+
6+
RUN pip install uv
7+
8+
WORKDIR /app
9+
# Install system dependencies
10+
COPY pyproject.toml uv.lock ./
11+
RUN --mount=type=cache,target=/root/.cache/uv \
12+
UV_COMPILE_BYTECODE=1 uv pip install --system .
13+
# Copy application code
14+
COPY apps/ ./apps/
15+
RUN python -m compileall -q .
16+
17+
# Create non-root user
18+
RUN useradd --create-home --shell /bin/bash app \
19+
&& chown -R app:app /app
20+
USER app
21+
22+
CMD ["streamlit", "run", "apps/vendor_app.py", "--server.port=3000"]

adk-sock-shop/Makefile

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
build-adk-image:
2+
docker buildx build --builder hydrobuild --platform linux/amd64,linux/arm64 --tag jimclark106/supplier_agent:latest --push --file Dockerfile .
3+
4+
build-adk-ui-image:
5+
docker buildx build --builder hydrobuild --platform linux/amd64,linux/arm64 --tag jimclark106/supplier_agent_ui:latest --push --file Dockerfile.adk-ui .
6+
7+
gateway-secrets:
8+
docker mcp secret set 'mongodb.connection_string=mongodb://admin:password@mongodb:27017/' && \
9+
docker mcp secret set 'resend.api_key=$(RESEND_API_KEY)' && \
10+
docker mcp secret set 'brave.api_key=$(BRAVE_API_KEY)' && \
11+
docker mcp secret export brave resend mongodb > ./.mcp.env && \
12+
echo $(OPENAI_API_KEY) > ./secret.openai-api-key
13+
14+
adk-api-server-start:
15+
MCPGATEWAY_ENDPOINT=http://localhost:8811/sse \
16+
MODEL_RUNNER_URL=http://localhost:12434/engines/llama.cpp/v1 \
17+
MODEL_RUNNER_MODEL=ai/qwen3:14B-Q6_K \
18+
uv run adk api_server --port 8000 --log_level DEBUG
19+
20+
adk-ui-start:
21+
API_BASE_URL=http://localhost:8000 \
22+
uv run streamlit run apps/vendor_app.py --server.port 3000
23+
24+
local-context:
25+
docker context use desktop-linux
26+
27+
local-compose-up:
28+
docker compose up front-end catalogue catalogue-db mongodb mcp-gateway
29+
30+
local-down:
31+
docker compose down
32+
33+
local-up: local-context local-compose-up
34+
35+
local-down: local-context local-down
36+
37+
offload-context:
38+
docker context use docker-cloud
39+
40+
offload-compose-up:
41+
docker compose -f compose.yaml -f compose.offload.yaml up --build
42+
43+
offload-up: offload-context offload-compose-up
44+
45+
offload-down:
46+
docker compose -f compose.yaml -f compose.offload.yaml down
47+

0 commit comments

Comments
 (0)