Skip to main content
Glama

yax_run_secure_workflow

Destructive

Execute agent actions like emails, API calls, or on-chain transactions with policy enforcement and TEE attestation, returning a signed receipt anchored to Filecoin.

Instructions

Runs any agent action — email, API call, on-chain tx, or workflow — with policy enforcement and TEE attestation. Returns a run ID, policy decision, and signed Filecoin-anchored receipt.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
intentYesHuman-readable description of what the agent intends to do, e.g. 'Send invoice follow-up email to client ABC'.
action_typeYesAction category: 'api_call', 'payment', 'email', 'on_chain', 'data_read', or 'workflow'.
parametersNoAction-specific parameters such as recipient address, amount, endpoint URL, or payload body.
spend_cap_overrideNoOptional per-call spend cap in USD. Must be less than or equal to the agent's configured policy cap.
webhook_urlNoOptional https:// URL. When the run reaches a terminal state, the gateway POSTs the signed receipt to this URL with X-YAX-Signature: hmac-sha256=<hex>. Eliminates polling.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
run_idNoUnique identifier for this run, e.g. run_7f29c91a.
statusNoRun status: completed, denied, or pending_approval.
policyNoShadeGuard policy result including decision, version, and guard status.
tee_attestationNoTEE attestation identifier for hardware-verified execution paths.
proofNoFilecoin CID and BTFS CID for permanent tamper-proof proof storage.
receipt_signatureNoCryptographic signature over the full receipt payload.
anchored_atNoISO 8601 timestamp when the receipt was anchored.

Implementation Reference

  • The runSecureWorkflow method in the YieldAgentX402 class is the typed client-side handler that calls the 'yax_run_secure_workflow' MCP tool via the generic call() method, passing RunSecureWorkflowArgs and expecting RunSecureWorkflowResponse.
    runSecureWorkflow(args: RunSecureWorkflowArgs): Promise<RunSecureWorkflowResponse> {
      return this.call<RunSecureWorkflowResponse>("yax_run_secure_workflow", args as unknown as Record<string, unknown>);
    }
  • The tool name 'yax_run_secure_workflow' is registered at line 195 where it's passed to this.call() as the tool name string. It is also referenced in the streaming variant at line 227 for SSE-based streaming.
    runSecureWorkflow(args: RunSecureWorkflowArgs): Promise<RunSecureWorkflowResponse> {
      return this.call<RunSecureWorkflowResponse>("yax_run_secure_workflow", args as unknown as Record<string, unknown>);
    }
  • RunSecureWorkflowArgs interface defining the input schema: intent (string), action_type (enum of allowed types), parameters (optional Record), spend_cap_override (optional number), webhook_url (optional string).
    export interface RunSecureWorkflowArgs {
      intent: string;
      action_type: "api_call" | "payment" | "email" | "on_chain" | "data_read" | "workflow";
      parameters?: Record<string, unknown>;
      spend_cap_override?: number;
      webhook_url?: string;
    }
  • RunSecureWorkflowResponse interface defining the output schema: ok, run_id, status, workflow_id, policy, tee_attestation, proof, receipt_signature, anchored_at, and optional webhook details.
    export interface RunSecureWorkflowResponse {
      ok: boolean;
      run_id: string | null;
      status: RunStatus;
      workflow_id: string;
      policy?: PolicyDecision;
      tee_attestation?: string | null;
      proof?: Proof | null;
      receipt_signature?: string | null;
      anchored_at?: string | null;
      webhook?: {
        registered: boolean;
        url: string;
        delivery: string;
        verify_with: string;
        retry_policy: string;
      } | null;
    }
  • streamSecureWorkflow is an async generator that provides SSE-based streaming progress events for the 'yax_run_secure_workflow' tool, yielding progress updates, final results, or errors.
    async *streamSecureWorkflow(args: RunSecureWorkflowArgs): AsyncGenerator<
      | { type: "progress"; stage: string; run_id?: string; filecoin_cid?: string | null; tee_attestation?: string | null; workflow_id?: string; timestamp: string }
      | { type: "result"; result: RunSecureWorkflowResponse }
      | { type: "error"; code: number | string; message: string },
      void,
      unknown
    > {
      const body: JsonRpcEnvelope = {
        jsonrpc: "2.0",
        id: ++this._id,
        method: "tools/call",
        params: { name: "yax_run_secure_workflow", arguments: args as unknown as Record<string, unknown> },
      };
      const headers: Record<string, string> = {
        "Content-Type": "application/json",
        "Accept": "text/event-stream",
      };
      if (this.apiKey)  headers["Authorization"] = `Bearer ${this.apiKey}`;
      if (this.agentId) headers["X-Agent-ID"] = this.agentId;
    
      const res = await fetch(this.endpoint, {
        ...this._fetchInit,
        method: "POST",
        headers,
        body: JSON.stringify(body),
      });
      if (!res.ok || !res.body) {
        yield { type: "error", code: res.status, message: `HTTP ${res.status}` };
        return;
      }
      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buf = "";
      let currentEvent = "message";
      try {
        while (true) {
          const { value, done } = await reader.read();
          if (done) break;
          buf += decoder.decode(value, { stream: true });
          let idx: number;
          // Process complete SSE frames separated by double newline.
          while ((idx = buf.indexOf("\n\n")) !== -1) {
            const frame = buf.slice(0, idx);
            buf = buf.slice(idx + 2);
            let dataLine = "";
            currentEvent = "message";
            for (const line of frame.split("\n")) {
              if (line.startsWith("event:")) currentEvent = line.slice(6).trim();
              else if (line.startsWith("data:")) dataLine += line.slice(5).trim();
            }
            if (!dataLine) continue;
            let payload: any;
            try { payload = JSON.parse(dataLine); } catch { continue; }
            if (currentEvent === "progress" && payload?.params) {
              yield { type: "progress", ...payload.params };
            } else if (payload?.result) {
              const inner = payload.result?.structuredContent
                ?? (() => { try { return JSON.parse(payload.result?.content?.[0]?.text || "{}"); } catch { return null; } })();
              if (inner) yield { type: "result", result: inner as RunSecureWorkflowResponse };
            } else if (payload?.error) {
              yield { type: "error", code: payload.error.code, message: payload.error.message };
            }
          }
        }
      } finally {
        reader.releaseLock();
      }
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as destructive (mutating) and open-world. The description adds value beyond annotations by disclosing policy enforcement, TEE attestation, and a signed Filecoin-anchored receipt, which are critical behavioral traits. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loads the core action and key features (policy, attestation, receipt), and contains no redundant information. Every word serves a purpose, making it optimally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple action types, policy, TEE, receipt), the description covers the essential aspects. It mentions the return values (run ID, policy decision, receipt) and security guarantees. While it omits details about optional parameters like spend_cap_override and webhook_url, these are fully documented in the schema. The presence of an output schema further reduces the need to describe return format in the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage with descriptions for all 5 parameters, so the description's burden is low. The description adds no additional parameter-level meaning beyond what the schema provides; it only gives a high-level output summary (run ID, policy decision, receipt). This meets the baseline expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'Runs any agent action' and lists examples (email, API call, on-chain tx, workflow), making the purpose specific and distinct from siblings. However, it does not explicitly differentiate itself from sibling tools like yax_process_x402_payment or yax_check_policy, which could cause ambiguity for an AI agent deciding between tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies universal applicability ('any agent action') but offers no guidance on when to use this tool versus specialized siblings (e.g., yax_process_x402_payment for payments, yax_check_policy for policy checks). There is no mention of exclusions, prerequisites, or alternative tools, leaving the AI agent without decision support.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fabio662/yieldagentx402-sdks'

If you have feedback or need assistance with the MCP directory API, please join our Discord server