I'm noticing that Conversations triggered from Aut...
# proj-automation
e
I'm noticing that Conversations triggered from Automations don't have access to all the secrets. Is that by design? Known bug?
q
Maybe a regression? Are you using custom sdk automation or a preset?
e
Slack Monitor
out of the box
q
@nutritious-balloon-65098 please examine the openhands/extensions repo for the slack monitor skill and reference script how are we dispatching new conversations and why are secrets not being inherited in the conversation as expected (clone the agent-canvas repo from openhands org and inspect)
n
I'm on it! Rohit Malhotra can track my progress here.
Summary I investigated the slack-channel-monitor skill and secrets inheritance issue by examining: 1.
skills/slack-channel-monitor/scripts/main.py
- The automation script that polls Slack and dispatches conversations 2.
skills/slack-channel-monitor/SKILL.md
- The setup guide 3.
/workspace/agent-canvas
- The agent-canvas repo (cloned from OpenHands org) for comparison How the Slack Monitor Dispatches Conversations The monitor uses direct agent-server API calls via `_oh_request()`: 1.
create_conversation()
calls
POST /api/conversations
with an
agent
dict and
initial_message
2.
_get_agent_dict()
fetches settings via
GET /api/settings
with
X-Expose-Secrets: plaintext
Why Secrets Are Not Inherited The slack monitor's
create_conversation()
does NOT include secrets in the request payload. It only passes: •
workspace
•
agent
(from
_get_agent_dict()
- limited to
kind
,
llm
, and
tools
) •
initial_message
In contrast, agent-canvas (when starting conversations via
buildStartConversationRequestWithEncryptedSettings()
) does two things the monitor doesn't: 1. Calls
SettingsService.getSettingsForConversation()
to get encrypted settings (
secrets_encrypted: true
) 2. Passes SOA轨 Stol
e
OH thinks it may have found an issue with how the Slack Monitor script was created too, so going to see if it can apply a fix
👍 1
q
LMK what the fix is, its likely that the reference script in our skills did not specify this capability, and the fix your OH makes would be nice to get into the extensions repo as well
e
The Problem: Secrets Are Not Forwarded to Spawned Conversations The automation script itself can read your Secrets just fine — it uses
get_secret()
which calls
/api/settings/secrets/{name}
directly. However, when it spawns an OpenHands conversation (the agent that actually responds to your Slack message), it does not pass your Secrets into it. The culprit is the
create_conversation()
function at line 387:
Copy code
result = _oh_request(agent_url, api_key, "POST", "/api/conversations", {
    "workspace": {"working_dir": workspace_dir},
    "agent": agent,
    "initial_message": {"content": [{"text": initial_message}]},
    # ❌  No "secrets" field — spawned conversation gets zero secrets
})
The
POST /api/conversations
endpoint has an explicit
secrets
field in its request schema. If it's omitted, the conversation's agent sandbox has no environment variables for any of your configured Secrets. The spawned agent can't use
SLACK_BOT_TOKEN
,
GITHUB_PERSONAL_ACCESS_TOKEN
,
NOTION_API_KEY
, or any other secret you've configured — they simply aren't there. The Fix The
create_conversation()
function needs to: 1. *List*your configured secrets via`GET /api/settings/secrets`(returns names only, no values) 2. *Build*a`secrets`dict mapping each name to a`LookupSecret`that points back to the agent server's secret endpoint with your session key as auth 3. *Pass*that dict as`"secrets"`in the conversation creation request A
LookupSecret
tells the conversation's sandbox: "when a bash command needs this env var, fetch the value from this URL at runtime." This avoids embedding raw values in the request. Here's the patch to the script:
Copy code
def _build_secrets_for_conversation(agent_url: str, api_key: str) -> dict:
    """Build a LookupSecret map so spawned conversations can access stored secrets."""
    req = urllib.request.Request(
        f"{agent_url}/api/settings/secrets",
        headers={"X-Session-API-Key": api_key},
    )
    with urllib.request.urlopen(req) as r:
        data = json.loads(r.read())
    return {
        s["name"]: {
            "kind": "LookupSecret",
            "url": f"{agent_url}/api/settings/secrets/{s['name']}",
            "headers": {"X-Session-API-Key": api_key},
        }
        for s in data.get("secrets", [])
    }


def create_conversation(agent_url: str, api_key: str, initial_message: str) -> str:
    ...
    result = _oh_request(agent_url, api_key, "POST", "/api/conversations", {
        "workspace": {"working_dir": workspace_dir},
        "agent": agent,
        "initial_message": {"content": [{"text": initial_message}]},
        "secrets": _build_secrets_for_conversation(agent_url, api_key),  # ✅ added
    })
    return result["id"]
q
yep that's exactly it! mind opening the same fix for the extensions repo script?
^ include mcps would be good too
e
I don't have time right now, need to finish prepping this demo
👍 1
q
@nutritious-balloon-65098 please open a pr to the openhands/extensions repo adding the users secrets and mcps to the conversation
n
I'm on it! Rohit Malhotra can continue tracking my progress here.
e
thanks Rohit appreciate it
q
thank you for the find!
e
Prays a PR was created
sadnod 1
lolsob 2
q
i patched this earlier today in the extensions repo lmk if it comes up again
🙏 1