@1claw/cli 0.37.0 → 0.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundled-templates/registry.yaml +62 -0
- package/dist/bundled-templates/templates/agentkit/Dockerfile +28 -0
- package/dist/bundled-templates/templates/agentkit/README.md +36 -0
- package/dist/bundled-templates/templates/agentkit/agent.py +83 -0
- package/dist/bundled-templates/templates/agentkit/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/agentkit/requirements.txt +5 -0
- package/dist/bundled-templates/templates/agentkit/template.yaml +24 -0
- package/dist/bundled-templates/templates/agno/Dockerfile +28 -0
- package/dist/bundled-templates/templates/agno/README.md +36 -0
- package/dist/bundled-templates/templates/agno/agent.py +86 -0
- package/dist/bundled-templates/templates/agno/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/agno/requirements.txt +2 -0
- package/dist/bundled-templates/templates/agno/template.yaml +24 -0
- package/dist/bundled-templates/templates/coder/Dockerfile +28 -0
- package/dist/bundled-templates/templates/coder/README.md +36 -0
- package/dist/bundled-templates/templates/coder/agent.py +119 -0
- package/dist/bundled-templates/templates/coder/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/coder/requirements.txt +4 -0
- package/dist/bundled-templates/templates/coder/template.yaml +24 -0
- package/dist/bundled-templates/templates/crewai/Dockerfile +28 -0
- package/dist/bundled-templates/templates/crewai/README.md +29 -0
- package/dist/bundled-templates/templates/crewai/agent.py +109 -0
- package/dist/bundled-templates/templates/crewai/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/crewai/requirements.txt +3 -0
- package/dist/bundled-templates/templates/crewai/template.yaml +24 -0
- package/dist/bundled-templates/templates/elizaos/Dockerfile +31 -0
- package/dist/bundled-templates/templates/elizaos/README.md +36 -0
- package/dist/bundled-templates/templates/elizaos/agent.ts +100 -0
- package/dist/bundled-templates/templates/elizaos/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/elizaos/package.json +18 -0
- package/dist/bundled-templates/templates/elizaos/template.yaml +25 -0
- package/dist/bundled-templates/templates/elizaos/tsconfig.json +12 -0
- package/dist/bundled-templates/templates/langchain/Dockerfile +28 -0
- package/dist/bundled-templates/templates/langchain/README.md +37 -0
- package/dist/bundled-templates/templates/langchain/agent.py +115 -0
- package/dist/bundled-templates/templates/langchain/entrypoint.sh +36 -0
- package/dist/bundled-templates/templates/langchain/requirements.txt +4 -0
- package/dist/bundled-templates/templates/langchain/template.yaml +24 -0
- package/dist/bundled-templates/templates/llamaindex/Dockerfile +28 -0
- package/dist/bundled-templates/templates/llamaindex/README.md +36 -0
- package/dist/bundled-templates/templates/llamaindex/agent.py +97 -0
- package/dist/bundled-templates/templates/llamaindex/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/llamaindex/requirements.txt +3 -0
- package/dist/bundled-templates/templates/llamaindex/template.yaml +24 -0
- package/dist/bundled-templates/templates/mastra/Dockerfile +31 -0
- package/dist/bundled-templates/templates/mastra/README.md +31 -0
- package/dist/bundled-templates/templates/mastra/agent.ts +112 -0
- package/dist/bundled-templates/templates/mastra/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/mastra/package.json +17 -0
- package/dist/bundled-templates/templates/mastra/template.yaml +25 -0
- package/dist/bundled-templates/templates/mastra/tsconfig.json +12 -0
- package/dist/bundled-templates/templates/openai-agents/Dockerfile +28 -0
- package/dist/bundled-templates/templates/openai-agents/README.md +29 -0
- package/dist/bundled-templates/templates/openai-agents/agent.py +98 -0
- package/dist/bundled-templates/templates/openai-agents/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/openai-agents/requirements.txt +3 -0
- package/dist/bundled-templates/templates/openai-agents/template.yaml +24 -0
- package/dist/bundled-templates/templates/pydantic-ai/Dockerfile +28 -0
- package/dist/bundled-templates/templates/pydantic-ai/README.md +36 -0
- package/dist/bundled-templates/templates/pydantic-ai/agent.py +110 -0
- package/dist/bundled-templates/templates/pydantic-ai/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/pydantic-ai/requirements.txt +2 -0
- package/dist/bundled-templates/templates/pydantic-ai/template.yaml +24 -0
- package/dist/bundled-templates/templates/smolagents/Dockerfile +28 -0
- package/dist/bundled-templates/templates/smolagents/README.md +36 -0
- package/dist/bundled-templates/templates/smolagents/agent.py +97 -0
- package/dist/bundled-templates/templates/smolagents/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/smolagents/requirements.txt +2 -0
- package/dist/bundled-templates/templates/smolagents/template.yaml +24 -0
- package/dist/bundled-templates/templates/typescript-sdk/Dockerfile +31 -0
- package/dist/bundled-templates/templates/typescript-sdk/README.md +29 -0
- package/dist/bundled-templates/templates/typescript-sdk/agent.ts +130 -0
- package/dist/bundled-templates/templates/typescript-sdk/entrypoint.sh +34 -0
- package/dist/bundled-templates/templates/typescript-sdk/package.json +17 -0
- package/dist/bundled-templates/templates/typescript-sdk/template.yaml +25 -0
- package/dist/bundled-templates/templates/typescript-sdk/tsconfig.json +12 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +6 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/proxy.d.ts.map +1 -1
- package/dist/src/commands/proxy.js +4 -0
- package/dist/src/commands/proxy.js.map +1 -1
- package/dist/src/commands/spawn.d.ts.map +1 -1
- package/dist/src/commands/spawn.js +5 -1
- package/dist/src/commands/spawn.js.map +1 -1
- package/dist/src/lib/module-deprecation.d.ts +8 -0
- package/dist/src/lib/module-deprecation.d.ts.map +1 -0
- package/dist/src/lib/module-deprecation.js +15 -0
- package/dist/src/lib/module-deprecation.js.map +1 -0
- package/dist/src/lib/paths.d.ts +5 -4
- package/dist/src/lib/paths.d.ts.map +1 -1
- package/dist/src/lib/paths.js +27 -13
- package/dist/src/lib/paths.js.map +1 -1
- package/dist/src/registry.yaml +62 -0
- package/dist/src/templates/agentkit/Dockerfile +34 -0
- package/dist/src/templates/agentkit/README.md +36 -0
- package/dist/src/templates/agentkit/agent.py +83 -0
- package/dist/src/templates/agentkit/entrypoint.sh +34 -0
- package/dist/src/templates/agentkit/requirements.txt +5 -0
- package/dist/src/templates/agentkit/template.yaml +24 -0
- package/dist/src/templates/agno/Dockerfile +34 -0
- package/dist/src/templates/agno/README.md +36 -0
- package/dist/src/templates/agno/agent.py +86 -0
- package/dist/src/templates/agno/entrypoint.sh +34 -0
- package/dist/src/templates/agno/requirements.txt +2 -0
- package/dist/src/templates/agno/template.yaml +24 -0
- package/dist/src/templates/coder/Dockerfile +34 -0
- package/dist/src/templates/coder/README.md +36 -0
- package/dist/src/templates/coder/agent.py +119 -0
- package/dist/src/templates/coder/entrypoint.sh +34 -0
- package/dist/src/templates/coder/requirements.txt +4 -0
- package/dist/src/templates/coder/template.yaml +24 -0
- package/dist/src/templates/crewai/Dockerfile +34 -0
- package/dist/src/templates/crewai/README.md +29 -0
- package/dist/src/templates/crewai/agent.py +109 -0
- package/dist/src/templates/crewai/entrypoint.sh +34 -0
- package/dist/src/templates/crewai/requirements.txt +3 -0
- package/dist/src/templates/crewai/template.yaml +24 -0
- package/dist/src/templates/elizaos/Dockerfile +31 -0
- package/dist/src/templates/elizaos/README.md +36 -0
- package/dist/src/templates/elizaos/agent.ts +100 -0
- package/dist/src/templates/elizaos/entrypoint.sh +34 -0
- package/dist/src/templates/elizaos/package.json +18 -0
- package/dist/src/templates/elizaos/template.yaml +25 -0
- package/dist/src/templates/elizaos/tsconfig.json +12 -0
- package/dist/src/templates/fetcher.d.ts.map +1 -1
- package/dist/src/templates/fetcher.js +34 -15
- package/dist/src/templates/fetcher.js.map +1 -1
- package/dist/src/templates/langchain/Dockerfile +34 -0
- package/dist/src/templates/langchain/README.md +37 -0
- package/dist/src/templates/langchain/agent.py +115 -0
- package/dist/src/templates/langchain/entrypoint.sh +36 -0
- package/dist/src/templates/langchain/requirements.txt +4 -0
- package/dist/src/templates/langchain/template.yaml +24 -0
- package/dist/src/templates/llamaindex/Dockerfile +34 -0
- package/dist/src/templates/llamaindex/README.md +36 -0
- package/dist/src/templates/llamaindex/agent.py +97 -0
- package/dist/src/templates/llamaindex/entrypoint.sh +34 -0
- package/dist/src/templates/llamaindex/requirements.txt +3 -0
- package/dist/src/templates/llamaindex/template.yaml +24 -0
- package/dist/src/templates/mastra/Dockerfile +31 -0
- package/dist/src/templates/mastra/README.md +31 -0
- package/dist/src/templates/mastra/agent.ts +112 -0
- package/dist/src/templates/mastra/entrypoint.sh +34 -0
- package/dist/src/templates/mastra/package.json +17 -0
- package/dist/src/templates/mastra/template.yaml +25 -0
- package/dist/src/templates/mastra/tsconfig.json +12 -0
- package/dist/src/templates/openai-agents/Dockerfile +34 -0
- package/dist/src/templates/openai-agents/README.md +29 -0
- package/dist/src/templates/openai-agents/agent.py +98 -0
- package/dist/src/templates/openai-agents/entrypoint.sh +34 -0
- package/dist/src/templates/openai-agents/requirements.txt +3 -0
- package/dist/src/templates/openai-agents/template.yaml +24 -0
- package/dist/src/templates/pydantic-ai/Dockerfile +34 -0
- package/dist/src/templates/pydantic-ai/README.md +36 -0
- package/dist/src/templates/pydantic-ai/agent.py +110 -0
- package/dist/src/templates/pydantic-ai/entrypoint.sh +34 -0
- package/dist/src/templates/pydantic-ai/requirements.txt +2 -0
- package/dist/src/templates/pydantic-ai/template.yaml +24 -0
- package/dist/src/templates/smolagents/Dockerfile +34 -0
- package/dist/src/templates/smolagents/README.md +36 -0
- package/dist/src/templates/smolagents/agent.py +97 -0
- package/dist/src/templates/smolagents/entrypoint.sh +34 -0
- package/dist/src/templates/smolagents/requirements.txt +2 -0
- package/dist/src/templates/smolagents/template.yaml +24 -0
- package/dist/src/templates/typescript-sdk/Dockerfile +31 -0
- package/dist/src/templates/typescript-sdk/README.md +29 -0
- package/dist/src/templates/typescript-sdk/agent.ts +130 -0
- package/dist/src/templates/typescript-sdk/entrypoint.sh +34 -0
- package/dist/src/templates/typescript-sdk/package.json +17 -0
- package/dist/src/templates/typescript-sdk/template.yaml +25 -0
- package/dist/src/templates/typescript-sdk/tsconfig.json +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
4
|
+
curl tini && \
|
|
5
|
+
rm -rf /var/lib/apt/lists/*
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY requirements.txt .
|
|
10
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
11
|
+
|
|
12
|
+
COPY agent.py .
|
|
13
|
+
COPY entrypoint.sh .
|
|
14
|
+
RUN chmod +x entrypoint.sh
|
|
15
|
+
|
|
16
|
+
RUN mkdir -p /run/1claw
|
|
17
|
+
|
|
18
|
+
ENV NODE_ENV=production
|
|
19
|
+
ENV ONECLAW_DAEMON_SOCKET=/run/1claw/daemon.sock
|
|
20
|
+
ENV ONECLAW_FRAMEWORK=openai-agents
|
|
21
|
+
|
|
22
|
+
EXPOSE 3000
|
|
23
|
+
|
|
24
|
+
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=5 \
|
|
25
|
+
CMD curl -sf http://localhost:3000/health || exit 1
|
|
26
|
+
|
|
27
|
+
ENTRYPOINT ["tini", "--"]
|
|
28
|
+
CMD ["./entrypoint.sh"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# OpenAI Agents SDK Template
|
|
2
|
+
|
|
3
|
+
A Python agent using the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/)
|
|
4
|
+
with 1Claw MCP for secrets management and on-chain signing.
|
|
5
|
+
|
|
6
|
+
## Quick start
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
1claw spawn openai-agents
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or with your own API key:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
1claw spawn openai-agents --llm-api-key sk-...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What's included
|
|
19
|
+
|
|
20
|
+
- **agent.py** — Starter agent with function tools (hello_world, list_env_vars)
|
|
21
|
+
- **Flask server** on port 3000 with `/chat` and `/health` endpoints
|
|
22
|
+
- **Shroud integration** — LLM calls are routed through Shroud for inspection
|
|
23
|
+
- **MCP server** — started automatically for tool access to 1Claw vault
|
|
24
|
+
|
|
25
|
+
## Customizing
|
|
26
|
+
|
|
27
|
+
Edit `agent.py` to add your own `@function_tool` tools, change the agent
|
|
28
|
+
instructions, or add handoffs between agents. The agent uses the OpenAI
|
|
29
|
+
Agents SDK with the base URL pointed at Shroud.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenAI Agents SDK agent pre-wired with 1Claw MCP for secrets and signing.
|
|
3
|
+
|
|
4
|
+
LLM calls are routed through Shroud when ONECLAW_LLM_VIA_SHROUD is set.
|
|
5
|
+
The container never sees raw API keys — they are injected by the host daemon.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import asyncio
|
|
10
|
+
from flask import Flask, request, jsonify
|
|
11
|
+
from agents import Agent, Runner, function_tool, ModelSettings
|
|
12
|
+
|
|
13
|
+
app = Flask(__name__)
|
|
14
|
+
|
|
15
|
+
SHROUD_URL = os.environ.get("ONECLAW_SHROUD_URL", "https://shroud.1claw.xyz")
|
|
16
|
+
LLM_VIA_SHROUD = os.environ.get("ONECLAW_LLM_VIA_SHROUD", "").lower() == "true"
|
|
17
|
+
MODEL = os.environ.get("ONECLAW_SHROUD_MODEL", "gpt-4o-mini")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@function_tool
|
|
21
|
+
def hello_world(name: str) -> str:
|
|
22
|
+
"""Say hello to someone."""
|
|
23
|
+
return f"Hello, {name}! I'm an OpenAI Agents SDK agent running inside 1Claw."
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@function_tool
|
|
27
|
+
def list_env_vars() -> str:
|
|
28
|
+
"""List 1Claw-related environment variables (values redacted)."""
|
|
29
|
+
prefix = "ONECLAW_"
|
|
30
|
+
vars_list = [k for k in sorted(os.environ) if k.startswith(prefix)]
|
|
31
|
+
return "\n".join(f" {k}=***" for k in vars_list) if vars_list else "No ONECLAW_* vars set."
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create_agent() -> Agent | None:
|
|
35
|
+
"""Build the OpenAI agent. Returns None if no LLM is configured."""
|
|
36
|
+
if not LLM_VIA_SHROUD:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
os.environ["OPENAI_BASE_URL"] = f"{SHROUD_URL}/v1"
|
|
40
|
+
os.environ["OPENAI_API_KEY"] = "shroud-injected"
|
|
41
|
+
|
|
42
|
+
return Agent(
|
|
43
|
+
name="1Claw Agent",
|
|
44
|
+
instructions=(
|
|
45
|
+
"You are a helpful AI agent running inside a secure 1Claw container. "
|
|
46
|
+
"You have access to tools for greeting and inspecting the environment."
|
|
47
|
+
),
|
|
48
|
+
tools=[hello_world, list_env_vars],
|
|
49
|
+
model=MODEL,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
agent = create_agent()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@app.route("/health")
|
|
57
|
+
def health():
|
|
58
|
+
return jsonify({"status": "ok", "framework": "openai-agents", "llm_wired": LLM_VIA_SHROUD})
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@app.route("/chat", methods=["POST"])
|
|
62
|
+
def chat():
|
|
63
|
+
data = request.get_json(silent=True) or {}
|
|
64
|
+
message = data.get("message", "").strip()
|
|
65
|
+
if not message:
|
|
66
|
+
return jsonify({"error": "No message provided"}), 400
|
|
67
|
+
|
|
68
|
+
if not agent:
|
|
69
|
+
return jsonify({
|
|
70
|
+
"response": "No LLM configured. Use --llm-api-key or enable Token Billing.",
|
|
71
|
+
"framework": "openai-agents",
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
result = asyncio.run(Runner.run(agent, message))
|
|
76
|
+
output = result.final_output
|
|
77
|
+
return jsonify({"response": output, "framework": "openai-agents"})
|
|
78
|
+
except Exception as e:
|
|
79
|
+
return jsonify({"error": str(e)}), 500
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@app.route("/")
|
|
83
|
+
def index():
|
|
84
|
+
return """<!DOCTYPE html>
|
|
85
|
+
<html><head><title>1Claw OpenAI Agent</title></head>
|
|
86
|
+
<body style="font-family:system-ui;max-width:600px;margin:40px auto;padding:0 20px">
|
|
87
|
+
<h1>1Claw OpenAI Agents SDK</h1>
|
|
88
|
+
<p>Send messages via <code>POST /chat</code> with <code>{"message": "..."}</code></p>
|
|
89
|
+
<p>Health: <a href="/health">/health</a></p>
|
|
90
|
+
<p style="color:#666;font-size:0.9em">
|
|
91
|
+
Credentials stay in the host daemon — this container never sees secret values.
|
|
92
|
+
</p></body></html>"""
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
port = int(os.environ.get("CHAT_UI_PORT", "3000"))
|
|
97
|
+
print(f"OpenAI Agents SDK agent listening on http://0.0.0.0:{port}")
|
|
98
|
+
app.run(host="0.0.0.0", port=port)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
DAEMON_SOCKET="${ONECLAW_DAEMON_SOCKET:-/run/1claw/daemon.sock}"
|
|
5
|
+
CHAT_UI_PORT="${CHAT_UI_PORT:-3000}"
|
|
6
|
+
|
|
7
|
+
echo "─────────────────────────────────────────────"
|
|
8
|
+
echo " 1Claw OpenAI Agents SDK"
|
|
9
|
+
echo " Framework: openai-agents"
|
|
10
|
+
echo " Agent ID: ${ONECLAW_AGENT_ID:-not set}"
|
|
11
|
+
|
|
12
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
13
|
+
echo " Mode: ${ONECLAW_MODE:-cloud} (daemon socket)"
|
|
14
|
+
echo " Socket: $DAEMON_SOCKET"
|
|
15
|
+
else
|
|
16
|
+
echo " Mode: standalone (no daemon socket)"
|
|
17
|
+
fi
|
|
18
|
+
echo "─────────────────────────────────────────────"
|
|
19
|
+
|
|
20
|
+
if [ "$ONECLAW_LLM_VIA_SHROUD" = "true" ]; then
|
|
21
|
+
export OPENAI_BASE_URL="${ONECLAW_SHROUD_URL}/v1"
|
|
22
|
+
echo "LLM routed through Shroud: ${ONECLAW_SHROUD_PROVIDER}/${ONECLAW_SHROUD_MODEL}"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
26
|
+
if command -v 1claw-mcp >/dev/null 2>&1; then
|
|
27
|
+
ONECLAW_LOCAL_VAULT=true ONECLAW_DAEMON_SOCKET="$DAEMON_SOCKET" \
|
|
28
|
+
1claw-mcp --local 2>/tmp/mcp.log &
|
|
29
|
+
echo "MCP server started in background."
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "Ready: http://0.0.0.0:${CHAT_UI_PORT}"
|
|
34
|
+
exec python agent.py
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: openai-agents
|
|
2
|
+
display_name: "OpenAI Agents SDK"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "OpenAI Agents SDK with tool calling and 1Claw MCP integration"
|
|
5
|
+
author: 1Claw
|
|
6
|
+
language: python
|
|
7
|
+
homepage: https://openai.github.io/openai-agents-python/
|
|
8
|
+
|
|
9
|
+
docker:
|
|
10
|
+
base_image: python:3.12-slim
|
|
11
|
+
context_files:
|
|
12
|
+
- Dockerfile
|
|
13
|
+
- requirements.txt
|
|
14
|
+
- agent.py
|
|
15
|
+
- entrypoint.sh
|
|
16
|
+
env:
|
|
17
|
+
ONECLAW_FRAMEWORK: openai-agents
|
|
18
|
+
health_endpoint: /health
|
|
19
|
+
health_port: 3000
|
|
20
|
+
|
|
21
|
+
post_spawn_message: |
|
|
22
|
+
Edit agent.py to customize your OpenAI agent's tools and instructions.
|
|
23
|
+
Your 1Claw MCP server is available at the daemon socket.
|
|
24
|
+
LLM calls are routed through Shroud for inspection and redaction.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
4
|
+
curl tini && \
|
|
5
|
+
rm -rf /var/lib/apt/lists/*
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY requirements.txt .
|
|
10
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
11
|
+
|
|
12
|
+
COPY agent.py .
|
|
13
|
+
COPY entrypoint.sh .
|
|
14
|
+
RUN chmod +x entrypoint.sh
|
|
15
|
+
|
|
16
|
+
RUN mkdir -p /run/1claw
|
|
17
|
+
|
|
18
|
+
ENV NODE_ENV=production
|
|
19
|
+
ENV ONECLAW_DAEMON_SOCKET=/run/1claw/daemon.sock
|
|
20
|
+
ENV ONECLAW_FRAMEWORK=pydantic-ai
|
|
21
|
+
|
|
22
|
+
EXPOSE 3000
|
|
23
|
+
|
|
24
|
+
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=5 \
|
|
25
|
+
CMD curl -sf http://localhost:3000/health || exit 1
|
|
26
|
+
|
|
27
|
+
ENTRYPOINT ["tini", "--"]
|
|
28
|
+
CMD ["./entrypoint.sh"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Pydantic AI Template
|
|
2
|
+
|
|
3
|
+
A Python agent using [Pydantic AI](https://ai.pydantic.dev) for type-safe, structured agent interactions with 1Claw MCP.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
1claw spawn pydantic-ai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or with your own API key:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
1claw spawn pydantic-ai --llm-api-key sk-...
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## What's included
|
|
18
|
+
|
|
19
|
+
- **agent.py** — Pydantic AI agent with typed tools and dependency injection
|
|
20
|
+
- **Flask server** on port 3000 with `/chat` and `/health` endpoints
|
|
21
|
+
- **Shroud integration** — LLM calls are routed through Shroud for inspection
|
|
22
|
+
- **MCP server** — started automatically for tool access to 1Claw vault
|
|
23
|
+
|
|
24
|
+
## Customizing
|
|
25
|
+
|
|
26
|
+
Edit `agent.py` to define typed result models, add tools with
|
|
27
|
+
`RunContext` dependency injection, or use structured output validation.
|
|
28
|
+
Pydantic AI enforces type safety on tool inputs/outputs and agent results.
|
|
29
|
+
|
|
30
|
+
## LLM authentication
|
|
31
|
+
|
|
32
|
+
The template supports three methods (configured at spawn time):
|
|
33
|
+
|
|
34
|
+
1. **BYOK** — `1claw spawn pydantic-ai --llm-api-key sk-...`
|
|
35
|
+
2. **Token Billing** — enable in Dashboard, no key needed
|
|
36
|
+
3. **Anthropic WIF** — OIDC federation for Anthropic models
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pydantic AI agent pre-wired with 1Claw MCP for secrets and signing.
|
|
3
|
+
|
|
4
|
+
LLM calls are routed through Shroud when ONECLAW_LLM_VIA_SHROUD is set.
|
|
5
|
+
The container never sees raw API keys — they are injected by the host daemon.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import asyncio
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from flask import Flask, request, jsonify
|
|
12
|
+
from pydantic_ai import Agent, RunContext
|
|
13
|
+
from pydantic_ai.models.openai import OpenAIModel
|
|
14
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
|
15
|
+
|
|
16
|
+
app = Flask(__name__)
|
|
17
|
+
|
|
18
|
+
SHROUD_URL = os.environ.get("ONECLAW_SHROUD_URL", "https://shroud.1claw.xyz")
|
|
19
|
+
LLM_VIA_SHROUD = os.environ.get("ONECLAW_LLM_VIA_SHROUD", "").lower() == "true"
|
|
20
|
+
MODEL = os.environ.get("ONECLAW_SHROUD_MODEL", "gpt-4o-mini")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class AgentDeps:
|
|
25
|
+
agent_id: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def create_agent() -> Agent | None:
|
|
29
|
+
"""Build the Pydantic AI agent. Returns None if no LLM."""
|
|
30
|
+
if not LLM_VIA_SHROUD:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
model = OpenAIModel(
|
|
34
|
+
MODEL,
|
|
35
|
+
provider=OpenAIProvider(
|
|
36
|
+
base_url=f"{SHROUD_URL}/v1",
|
|
37
|
+
api_key="shroud-injected",
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
pydantic_agent = Agent(
|
|
42
|
+
model,
|
|
43
|
+
system_prompt=(
|
|
44
|
+
"You are a helpful AI agent running inside a secure 1Claw container. "
|
|
45
|
+
"You have access to tools for greeting and inspecting the environment."
|
|
46
|
+
),
|
|
47
|
+
deps_type=AgentDeps,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@pydantic_agent.tool
|
|
51
|
+
async def hello_world(ctx: RunContext[AgentDeps], name: str) -> str:
|
|
52
|
+
"""Say hello to someone."""
|
|
53
|
+
return f"Hello, {name}! I'm a Pydantic AI agent (agent: {ctx.deps.agent_id})."
|
|
54
|
+
|
|
55
|
+
@pydantic_agent.tool
|
|
56
|
+
async def list_env_vars(ctx: RunContext[AgentDeps]) -> str:
|
|
57
|
+
"""List 1Claw-related environment variables (values redacted)."""
|
|
58
|
+
prefix = "ONECLAW_"
|
|
59
|
+
vars_list = [k for k in sorted(os.environ) if k.startswith(prefix)]
|
|
60
|
+
return "\n".join(f" {k}=***" for k in vars_list) if vars_list else "No ONECLAW_* vars set."
|
|
61
|
+
|
|
62
|
+
return pydantic_agent
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
agent = create_agent()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@app.route("/health")
|
|
69
|
+
def health():
|
|
70
|
+
return jsonify({"status": "ok", "framework": "pydantic-ai", "llm_wired": LLM_VIA_SHROUD})
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@app.route("/chat", methods=["POST"])
|
|
74
|
+
def chat():
|
|
75
|
+
data = request.get_json(silent=True) or {}
|
|
76
|
+
message = data.get("message", "").strip()
|
|
77
|
+
if not message:
|
|
78
|
+
return jsonify({"error": "No message provided"}), 400
|
|
79
|
+
|
|
80
|
+
if not agent:
|
|
81
|
+
return jsonify({
|
|
82
|
+
"response": "No LLM configured. Use --llm-api-key or enable Token Billing.",
|
|
83
|
+
"framework": "pydantic-ai",
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
deps = AgentDeps(agent_id=os.environ.get("ONECLAW_AGENT_ID", "unknown"))
|
|
88
|
+
result = asyncio.run(agent.run(message, deps=deps))
|
|
89
|
+
return jsonify({"response": result.output, "framework": "pydantic-ai"})
|
|
90
|
+
except Exception as e:
|
|
91
|
+
return jsonify({"error": str(e)}), 500
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@app.route("/")
|
|
95
|
+
def index():
|
|
96
|
+
return """<!DOCTYPE html>
|
|
97
|
+
<html><head><title>1Claw Pydantic AI Agent</title></head>
|
|
98
|
+
<body style="font-family:system-ui;max-width:600px;margin:40px auto;padding:0 20px">
|
|
99
|
+
<h1>1Claw Pydantic AI Agent</h1>
|
|
100
|
+
<p>Send messages via <code>POST /chat</code> with <code>{"message": "..."}</code></p>
|
|
101
|
+
<p>Health: <a href="/health">/health</a></p>
|
|
102
|
+
<p style="color:#666;font-size:0.9em">
|
|
103
|
+
Credentials stay in the host daemon — this container never sees secret values.
|
|
104
|
+
</p></body></html>"""
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
port = int(os.environ.get("CHAT_UI_PORT", "3000"))
|
|
109
|
+
print(f"Pydantic AI agent listening on http://0.0.0.0:{port}")
|
|
110
|
+
app.run(host="0.0.0.0", port=port)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
DAEMON_SOCKET="${ONECLAW_DAEMON_SOCKET:-/run/1claw/daemon.sock}"
|
|
5
|
+
CHAT_UI_PORT="${CHAT_UI_PORT:-3000}"
|
|
6
|
+
|
|
7
|
+
echo "─────────────────────────────────────────────"
|
|
8
|
+
echo " 1Claw Pydantic AI Agent"
|
|
9
|
+
echo " Framework: pydantic-ai"
|
|
10
|
+
echo " Agent ID: ${ONECLAW_AGENT_ID:-not set}"
|
|
11
|
+
|
|
12
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
13
|
+
echo " Mode: ${ONECLAW_MODE:-cloud} (daemon socket)"
|
|
14
|
+
echo " Socket: $DAEMON_SOCKET"
|
|
15
|
+
else
|
|
16
|
+
echo " Mode: standalone (no daemon socket)"
|
|
17
|
+
fi
|
|
18
|
+
echo "─────────────────────────────────────────────"
|
|
19
|
+
|
|
20
|
+
if [ "$ONECLAW_LLM_VIA_SHROUD" = "true" ]; then
|
|
21
|
+
export OPENAI_BASE_URL="${ONECLAW_SHROUD_URL}/v1"
|
|
22
|
+
echo "LLM routed through Shroud: ${ONECLAW_SHROUD_PROVIDER}/${ONECLAW_SHROUD_MODEL}"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
26
|
+
if command -v 1claw-mcp >/dev/null 2>&1; then
|
|
27
|
+
ONECLAW_LOCAL_VAULT=true ONECLAW_DAEMON_SOCKET="$DAEMON_SOCKET" \
|
|
28
|
+
1claw-mcp --local 2>/tmp/mcp.log &
|
|
29
|
+
echo "MCP server started in background."
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "Ready: http://0.0.0.0:${CHAT_UI_PORT}"
|
|
34
|
+
exec python agent.py
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: pydantic-ai
|
|
2
|
+
display_name: "Pydantic AI"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Type-safe Python agent with structured output"
|
|
5
|
+
author: 1Claw
|
|
6
|
+
language: python
|
|
7
|
+
homepage: https://ai.pydantic.dev
|
|
8
|
+
|
|
9
|
+
docker:
|
|
10
|
+
base_image: python:3.12-slim
|
|
11
|
+
context_files:
|
|
12
|
+
- Dockerfile
|
|
13
|
+
- requirements.txt
|
|
14
|
+
- agent.py
|
|
15
|
+
- entrypoint.sh
|
|
16
|
+
env:
|
|
17
|
+
ONECLAW_FRAMEWORK: pydantic-ai
|
|
18
|
+
health_endpoint: /health
|
|
19
|
+
health_port: 3000
|
|
20
|
+
|
|
21
|
+
post_spawn_message: |
|
|
22
|
+
Edit agent.py to define your typed tools and result models.
|
|
23
|
+
Your 1Claw MCP server is available at the daemon socket.
|
|
24
|
+
LLM calls are routed through Shroud for inspection and redaction.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
4
|
+
curl tini && \
|
|
5
|
+
rm -rf /var/lib/apt/lists/*
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY requirements.txt .
|
|
10
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
11
|
+
|
|
12
|
+
COPY agent.py .
|
|
13
|
+
COPY entrypoint.sh .
|
|
14
|
+
RUN chmod +x entrypoint.sh
|
|
15
|
+
|
|
16
|
+
RUN mkdir -p /run/1claw
|
|
17
|
+
|
|
18
|
+
ENV NODE_ENV=production
|
|
19
|
+
ENV ONECLAW_DAEMON_SOCKET=/run/1claw/daemon.sock
|
|
20
|
+
ENV ONECLAW_FRAMEWORK=smolagents
|
|
21
|
+
|
|
22
|
+
EXPOSE 3000
|
|
23
|
+
|
|
24
|
+
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=5 \
|
|
25
|
+
CMD curl -sf http://localhost:3000/health || exit 1
|
|
26
|
+
|
|
27
|
+
ENTRYPOINT ["tini", "--"]
|
|
28
|
+
CMD ["./entrypoint.sh"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# HuggingFace smolagents Template
|
|
2
|
+
|
|
3
|
+
A Python agent using [smolagents](https://huggingface.co/docs/smolagents) — HuggingFace's lightweight agent framework — with 1Claw MCP for secrets management.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
1claw spawn smolagents
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or with your own API key:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
1claw spawn smolagents --llm-api-key sk-...
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## What's included
|
|
18
|
+
|
|
19
|
+
- **agent.py** — CodeAgent with example tools (hello_world, list_env_vars)
|
|
20
|
+
- **Flask server** on port 3000 with `/chat` and `/health` endpoints
|
|
21
|
+
- **Shroud integration** — LLM calls are routed through Shroud for inspection
|
|
22
|
+
- **MCP server** — started automatically for tool access to 1Claw vault
|
|
23
|
+
|
|
24
|
+
## Customizing
|
|
25
|
+
|
|
26
|
+
Edit `agent.py` to add custom tools, switch to `ToolCallingAgent`, or
|
|
27
|
+
use HuggingFace Hub models directly. smolagents supports both code-based
|
|
28
|
+
and tool-calling agent patterns.
|
|
29
|
+
|
|
30
|
+
## LLM authentication
|
|
31
|
+
|
|
32
|
+
The template supports three methods (configured at spawn time):
|
|
33
|
+
|
|
34
|
+
1. **BYOK** — `1claw spawn smolagents --llm-api-key sk-...`
|
|
35
|
+
2. **Token Billing** — enable in Dashboard, no key needed
|
|
36
|
+
3. **Anthropic WIF** — OIDC federation for Anthropic models
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HuggingFace smolagents agent pre-wired with 1Claw MCP for secrets and signing.
|
|
3
|
+
|
|
4
|
+
LLM calls are routed through Shroud when ONECLAW_LLM_VIA_SHROUD is set.
|
|
5
|
+
The container never sees raw API keys — they are injected by the host daemon.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from flask import Flask, request, jsonify
|
|
10
|
+
from smolagents import CodeAgent, tool, OpenAIServerModel
|
|
11
|
+
|
|
12
|
+
app = Flask(__name__)
|
|
13
|
+
|
|
14
|
+
SHROUD_URL = os.environ.get("ONECLAW_SHROUD_URL", "https://shroud.1claw.xyz")
|
|
15
|
+
LLM_VIA_SHROUD = os.environ.get("ONECLAW_LLM_VIA_SHROUD", "").lower() == "true"
|
|
16
|
+
MODEL = os.environ.get("ONECLAW_SHROUD_MODEL", "gpt-4o-mini")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@tool
|
|
20
|
+
def hello_world(name: str) -> str:
|
|
21
|
+
"""Say hello to someone.
|
|
22
|
+
Args:
|
|
23
|
+
name: the person to greet
|
|
24
|
+
"""
|
|
25
|
+
return f"Hello, {name}! I'm a smolagents agent running inside 1Claw."
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@tool
|
|
29
|
+
def list_env_vars() -> str:
|
|
30
|
+
"""List 1Claw-related environment variables (values redacted)."""
|
|
31
|
+
prefix = "ONECLAW_"
|
|
32
|
+
vars_list = [k for k in sorted(os.environ) if k.startswith(prefix)]
|
|
33
|
+
return "\n".join(f" {k}=***" for k in vars_list) if vars_list else "No ONECLAW_* vars set."
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def create_agent():
|
|
37
|
+
"""Build the smolagents CodeAgent. Returns None if no LLM."""
|
|
38
|
+
if not LLM_VIA_SHROUD:
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
model = OpenAIServerModel(
|
|
42
|
+
model_id=MODEL,
|
|
43
|
+
api_base=f"{SHROUD_URL}/v1",
|
|
44
|
+
api_key="shroud-injected",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return CodeAgent(
|
|
48
|
+
tools=[hello_world, list_env_vars],
|
|
49
|
+
model=model,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
agent = create_agent()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@app.route("/health")
|
|
57
|
+
def health():
|
|
58
|
+
return jsonify({"status": "ok", "framework": "smolagents", "llm_wired": LLM_VIA_SHROUD})
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@app.route("/chat", methods=["POST"])
|
|
62
|
+
def chat():
|
|
63
|
+
data = request.get_json(silent=True) or {}
|
|
64
|
+
message = data.get("message", "").strip()
|
|
65
|
+
if not message:
|
|
66
|
+
return jsonify({"error": "No message provided"}), 400
|
|
67
|
+
|
|
68
|
+
if not agent:
|
|
69
|
+
return jsonify({
|
|
70
|
+
"response": "No LLM configured. Use --llm-api-key or enable Token Billing.",
|
|
71
|
+
"framework": "smolagents",
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
result = agent.run(message)
|
|
76
|
+
return jsonify({"response": str(result), "framework": "smolagents"})
|
|
77
|
+
except Exception as e:
|
|
78
|
+
return jsonify({"error": str(e)}), 500
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@app.route("/")
|
|
82
|
+
def index():
|
|
83
|
+
return """<!DOCTYPE html>
|
|
84
|
+
<html><head><title>1Claw smolagents Agent</title></head>
|
|
85
|
+
<body style="font-family:system-ui;max-width:600px;margin:40px auto;padding:0 20px">
|
|
86
|
+
<h1>1Claw HuggingFace smolagents</h1>
|
|
87
|
+
<p>Send messages via <code>POST /chat</code> with <code>{"message": "..."}</code></p>
|
|
88
|
+
<p>Health: <a href="/health">/health</a></p>
|
|
89
|
+
<p style="color:#666;font-size:0.9em">
|
|
90
|
+
Credentials stay in the host daemon — this container never sees secret values.
|
|
91
|
+
</p></body></html>"""
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
port = int(os.environ.get("CHAT_UI_PORT", "3000"))
|
|
96
|
+
print(f"smolagents agent listening on http://0.0.0.0:{port}")
|
|
97
|
+
app.run(host="0.0.0.0", port=port)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
DAEMON_SOCKET="${ONECLAW_DAEMON_SOCKET:-/run/1claw/daemon.sock}"
|
|
5
|
+
CHAT_UI_PORT="${CHAT_UI_PORT:-3000}"
|
|
6
|
+
|
|
7
|
+
echo "─────────────────────────────────────────────"
|
|
8
|
+
echo " 1Claw smolagents Agent"
|
|
9
|
+
echo " Framework: smolagents"
|
|
10
|
+
echo " Agent ID: ${ONECLAW_AGENT_ID:-not set}"
|
|
11
|
+
|
|
12
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
13
|
+
echo " Mode: ${ONECLAW_MODE:-cloud} (daemon socket)"
|
|
14
|
+
echo " Socket: $DAEMON_SOCKET"
|
|
15
|
+
else
|
|
16
|
+
echo " Mode: standalone (no daemon socket)"
|
|
17
|
+
fi
|
|
18
|
+
echo "─────────────────────────────────────────────"
|
|
19
|
+
|
|
20
|
+
if [ "$ONECLAW_LLM_VIA_SHROUD" = "true" ]; then
|
|
21
|
+
export OPENAI_BASE_URL="${ONECLAW_SHROUD_URL}/v1"
|
|
22
|
+
echo "LLM routed through Shroud: ${ONECLAW_SHROUD_PROVIDER}/${ONECLAW_SHROUD_MODEL}"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [ -S "$DAEMON_SOCKET" ]; then
|
|
26
|
+
if command -v 1claw-mcp >/dev/null 2>&1; then
|
|
27
|
+
ONECLAW_LOCAL_VAULT=true ONECLAW_DAEMON_SOCKET="$DAEMON_SOCKET" \
|
|
28
|
+
1claw-mcp --local 2>/tmp/mcp.log &
|
|
29
|
+
echo "MCP server started in background."
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "Ready: http://0.0.0.0:${CHAT_UI_PORT}"
|
|
34
|
+
exec python agent.py
|