1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
"""LangChain agent with secretsh-protected shell tool.
Usage:
pip install secretsh langchain
python langchain_shell_tool_demo.py
Quoting guide for the agent
---------------------------
The shell tool accepts a natural command string. Because secretsh parses it
directly (no parent shell involved), single quotes inside the string work as
expected:
# Header with a space — single-quote the header value
shell("curl -sS -H 'X-Api-Key: {{NINJA_API_KEY}}' 'https://api.api-ninjas.com/v2/quoteoftheday'")
# jq filter with pipe and comparison
shell("jq '.results[] | select(.score > 90)' data.json")
# awk program with $ field references
shell("awk '$2 > 10' file.txt")
# URL with & — single-quote the URL
shell("curl 'https://api.example.com/search?q=hello&limit=10'")
# Pipe to jq — use the parent shell pipe, not inside the command string
import subprocess
result = shell("curl -sS -H 'X-Api-Key: {{NINJA_API_KEY}}' 'https://api.api-ninjas.com/v2/quoteoftheday'")
# then: subprocess / LangChain chain to pipe result.stdout through jq
Available secret keys are listed in PlaceholderError if a key is missing.
"""
= . /
"""Execute a command with secrets injected from the .env file.
Secrets are referenced using {{SECRET_NAME}} syntax — never put raw
secret values in the command string. Secret values are automatically
redacted from all output returned to you.
Write the command as a natural shell string. Use single quotes for
arguments containing spaces, pipes, $ signs, or & characters:
curl -sS -H 'X-Api-Key: {{NINJA_API_KEY}}' 'https://api.api-ninjas.com/v2/quoteoftheday'
jq '.results[] | select(.score > 90)' data.json
awk '$2 > 10' file.txt
curl 'https://api.example.com/search?q=hello&limit=10'
If a secret key is not found, the error message lists all available keys.
Args:
command: Shell command string with optional {{KEY_NAME}} placeholders.
"""
return f
=
=
+=
+= f
return
return f
return f
return f
# demonstrates available-keys error
# Example output:
# Shell tool demo:
# API key is [REDACTED_DEMO_API_KEY]
#
# DB password is [REDACTED_DB_PASSWORD]
#
# {"headers": {"Accept": "*/*", "Host": "httpbin.org", "X-Api-Key": "[REDACTED_DEMO_API_KEY]", ...}}
#
# Secret not found: secretsh error: placeholder error: "MISSING_KEY" not found in env file; available keys: [AWS_ACCESS_KEY_ID, ...]