Skip to main content
Glama

get_agent_status

Retrieve detailed status of an agent including active state, balance, strategy, daily activity, recent log, and position history. Monitor agent health and debug issues.

Instructions

Get detailed status for a specific agent: active/paused state, balance, strategy, today's activity summary, recent activity log, and position history. Use this to monitor agent health and debug issues.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
agent_idNoThe agent's profile ID. Auto-filled from saved credentials if omitted.
owner_idNoThe owner's profile ID. Auto-filled from saved credentials if omitted.

Implementation Reference

  • Handler for the get_agent_status tool. Calls the update-agent API with action 'agent_status' to fetch agent details (status, balance, compiled rules, today's activity, activity log, recent bets). Also fetches on-chain balance via Solana RPC.
    server.tool(
      "get_agent_status",
      "Get detailed status for a specific agent: active/paused state, balance, strategy, today's activity summary, recent activity log, and position history. Use this to monitor agent health and debug issues.",
      {
        agent_id: z.string().optional().describe("The agent's profile ID. Auto-filled from saved credentials if omitted."),
        owner_id: z.string().optional().describe("The owner's profile ID. Auto-filled from saved credentials if omitted."),
      },
      async ({ agent_id, owner_id }) => {
        const saved = loadSavedAgents();
        const resolvedAgent = agent_id || (saved.length > 0 ? saved[saved.length - 1].agentId : null);
        const resolvedOwner = owner_id || (saved.length > 0 ? saved[saved.length - 1].ownerId : null);
        if (!resolvedAgent || !resolvedOwner) {
          return { content: [{ type: "text", text: "No agent found. Create one first with `create_agent`, or pass agent_id and owner_id." }], isError: true };
        }
    
        const result = (await apiPost("update-agent", {
          action: "agent_status",
          agentId: resolvedAgent,
          ownerProfileId: resolvedOwner,
        })) as any;
    
        if (!result.success) {
          return {
            content: [{ type: "text", text: `Status check failed: ${result.error || "Unknown error"}` }],
            isError: true,
          };
        }
    
        const agent = result.agent || {};
        const today = result.today || {};
        const activityLog = result.activityLog || [];
        const recentBets = result.recentBets || [];
    
        // Fetch on-chain balance
        const onChainBalance = agent.walletAddress ? await fetchOnChainBalance(agent.walletAddress) : null;
    
        // Format compiled rules summary
        const compiled = agent.compiledRules;
        let compiledSummary = "  No compiled rules";
        if (compiled?.rules?.length) {
          const ruleLines = compiled.rules.map((r: any, i: number) => {
            const cond = r.condition || {};
            const act = r.action || {};
            const condDesc = cond.type === "always" ? "Every pool"
              : cond.type === "win_probability" ? `Win prob >${cond.probability_threshold_pct || 60}%`
              : cond.type === "pool_imbalance" ? `Pool imbalance >${cond.imbalance_threshold_pct || 60}%`
              : cond.type === "token_preference" ? `Tokens: ${cond.include_tokens?.join(",") || "any"}`
              : cond.type === "time_window" ? `Time: ${cond.min_hours_remaining ?? 0}-${cond.max_hours_remaining ?? 24}h`
              : cond.type;
            const timeFilter = (cond.type !== "time_window" && (cond.min_hours_remaining != null || cond.max_hours_remaining != null))
              ? ` (${cond.min_hours_remaining != null ? `>${cond.min_hours_remaining}h` : ""}${cond.max_hours_remaining != null ? `<${cond.max_hours_remaining}h` : ""})`
              : "";
            const poolFilter = cond.min_pool_size_usdc ? ` (pool>=$${cond.min_pool_size_usdc})` : "";
            const amtType = act.amount_type || "fixed";
            const amount = amtType === "full_balance" ? "full budget"
              : amtType === "split_equal" ? "split equally"
              : amtType === "percentage" ? `${act.amount_percent || 10}% of budget`
              : `$${act.amount_usdc || 1}`;
            return `  ${i + 1}. ${condDesc}${timeFilter}${poolFilter} → ${amount} on ${act.side_selection || "high_prob"}`;
          });
          const gc = compiled.global_constraints || {};
          const constraints = [
            gc.max_daily_spend_usdc ? `$${gc.max_daily_spend_usdc}/day` : null,
            gc.max_bets_per_pool ? `${gc.max_bets_per_pool}/pool` : null,
            gc.cooldown_minutes ? `${gc.cooldown_minutes}min cooldown` : null,
          ].filter(Boolean).join(", ");
          compiledSummary = ruleLines.join("\n") + (constraints ? `\n  Constraints: ${constraints}` : "");
        }
    
        // Format activity log
        const activityLines = activityLog.length > 0
          ? activityLog.map((a: any) => {
              const time = a.at ? new Date(a.at).toISOString().replace("T", " ").slice(0, 19) : "?";
              const details = typeof a.details === "string" ? a.details : JSON.stringify(a.details || "");
              return `  ${time} — ${a.action}: ${humanizeError(details)}`;
            }).join("\n")
          : "  No recent activity";
    
        // Format recent bets
        const betLines = recentBets.length > 0
          ? recentBets.map((b: any) => {
              const time = b.at ? new Date(b.at).toISOString().replace("T", " ").slice(0, 19) : "?";
              const status = b.won === true ? "WON" : b.won === false ? "LOST" : "PENDING";
              const claimed = b.claimed ? " (claimed)" : "";
              return `  ${time} | ${b.pair} → ${b.side} $${b.amount} | conv ${b.conviction?.toFixed(3) ?? "?"} | ${status}${claimed}`;
            }).join("\n")
          : "  No recent entries";
    
        return {
          content: [
            {
              type: "text",
              text: [
                `# Agent Status: ${agent.name || resolvedAgent}`,
                "",
                `**Status:** ${agent.active ? "ACTIVE" : "PAUSED"}`,
                `**Balance:** ${onChainBalance != null ? `${onChainBalance.toFixed(2)} bsUSD (on-chain)` : `$${agent.balance?.toFixed(2) ?? "?"} (db)`}`,
                `**Wallet:** ${agent.walletAddress || "unknown"}`,
                `**Created:** ${agent.createdAt || "?"}`,
                "",
                `**Strategy:** ${agent.rules || "none"}`,
                "",
                `## Compiled Rules`,
                compiledSummary,
                "",
                `## Today's Activity`,
                `  Entries placed: ${today.betsCount ?? 0}`,
                `  Total spent: $${today.spend?.toFixed(2) ?? "0.00"}`,
                "",
                `## Recent Activity Log (last 20)`,
                activityLines,
                "",
                `## Recent Entries (last 20)`,
                betLines,
                "",
                `_Fetched at ${new Date().toISOString()}_`,
              ].join("\n"),
            },
          ],
        };
      }
    );
  • Input schema for get_agent_status: takes optional agent_id and owner_id parameters, both auto-filled from saved credentials.
      agent_id: z.string().optional().describe("The agent's profile ID. Auto-filled from saved credentials if omitted."),
      owner_id: z.string().optional().describe("The owner's profile ID. Auto-filled from saved credentials if omitted."),
    },
  • Registration of the 'get_agent_status' tool on the MCP server instance.
    server.tool(
  • Helper function used by get_agent_status to fetch the on-chain bsUSD token balance for the agent's wallet address via Solana JSON-RPC.
    async function fetchOnChainBalance(walletAddress: string): Promise<number | null> {
      try {
        // getTokenAccountsByOwner to find the bsUSD ATA and its balance
        const resp = await fetch(SOLANA_RPC, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            jsonrpc: "2.0",
            id: 1,
            method: "getTokenAccountsByOwner",
            params: [
              walletAddress,
              { mint: BSUSD_MINT },
              { encoding: "jsonParsed" },
            ],
          }),
        });
        const data = await resp.json() as any;
        const accounts = data?.result?.value || [];
        if (accounts.length === 0) return 0;
        const info = accounts[0]?.account?.data?.parsed?.info;
        return info?.tokenAmount?.uiAmount ?? 0;
      } catch {
        return null;
      }
    }
  • Helper function used by get_agent_status to load locally saved agent credentials from ~/.conviction/agents.json for auto-filling agent_id and owner_id.
    function loadSavedAgents(): SavedAgent[] {
      try {
        if (!existsSync(CRED_FILE)) return [];
        return JSON.parse(readFileSync(CRED_FILE, "utf-8"));
      } catch {
        return [];
      }
    }
    
    function saveAgents(agents: SavedAgent[]): void {
      try {
        if (!existsSync(CRED_DIR)) mkdirSync(CRED_DIR, { recursive: true, mode: 0o700 });
        writeFileSync(CRED_FILE, JSON.stringify(agents, null, 2), { mode: 0o600 });
      } catch (e: any) {
        console.error(`[conviction-mcp] Failed to save credentials: ${e.message}`);
      }
    }
    
    function addSavedAgent(agent: SavedAgent): void {
      const agents = loadSavedAgents();
      // Replace if same agentId exists, else append
      const idx = agents.findIndex((a) => a.agentId === agent.agentId);
      if (idx >= 0) agents[idx] = agent;
      else agents.push(agent);
      saveAgents(agents);
    }
    
    function getDefaultApiKey(): string | null {
      // Check env var first
      const envKey = process.env.CONVICTION_API_KEY;
      if (envKey) return envKey;
      // Fall back to most recently created saved agent
      const agents = loadSavedAgents();
      return agents.length > 0 ? agents[agents.length - 1].apiKey : null;
    }
Behavior4/5

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

Lists returned data: state, balance, strategy, activity summary, log, position history. No annotations, so description provides transparency. Does not discuss data freshness or auth, but covers key behavioral aspects.

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?

Single sentence efficiently lists output components and use case. No wasted words.

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?

No output schema, but description lists components of return value. With two optional auto-filled parameters, coverage is adequate. Minor gap: no explanation of exact field names.

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

Parameters4/5

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

Schema coverage 100%, but description adds value: 'Auto-filled from saved credentials if omitted' clarifies optionality and auto-fill behavior. Provides context beyond schema.

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

Purpose5/5

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

Description specifies verb 'Get detailed status' and resource 'specific agent', listing output categories. Distinguishes from siblings like 'get_my_agents' (list) and 'toggle_agent' (change state).

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

Usage Guidelines4/5

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

States use case: 'monitor agent health and debug issues'. No explicit when-not-to-use, but sibling context implies alternatives. Clear enough.

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/abcxz/conviction-fm'

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