Skip to main content
Glama

tool_get_answer_groups

Retrieve clustered student answer groups for AI-assisted grading to grade similar responses collectively instead of individually.

Instructions

List all answer groups for a question (AI-Assisted Grading).

Shows clusters of similar student answers. Grade one group to
grade all members at once — much more efficient than 1-by-1.

Args:
    course_id: The Gradescope course ID.
    question_id: The question ID.
    output_format: "markdown" or "json" for structured output.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
course_idYes
question_idYes
output_formatNomarkdown

Implementation Reference

  • Registration of the tool tool_get_answer_groups.
    def tool_get_answer_groups(
        course_id: str,
        question_id: str,
        output_format: str = "markdown",
    ) -> str:
        """List all answer groups for a question (AI-Assisted Grading).
    
        Shows clusters of similar student answers. Grade one group to
        grade all members at once — much more efficient than 1-by-1.
    
        Args:
            course_id: The Gradescope course ID.
            question_id: The question ID.
            output_format: "markdown" or "json" for structured output.
        """
        return get_answer_groups(course_id, question_id, output_format)
  • The actual handler function for getting answer groups.
    def get_answer_groups(
        course_id: str,
        question_id: str,
        output_format: str = "markdown",
    ) -> str:
        """List all answer groups for a question.
    
        Answer groups cluster similar student answers together for efficient
        batch grading. Instead of grading each submission individually, you
        can grade one group and the score applies to all members.
    
        Args:
            course_id: The Gradescope course ID.
            question_id: The question ID.
            output_format: "markdown" (default) or "json" for structured output.
        """
        if not course_id or not question_id:
            return "Error: course_id and question_id are required."
    
        try:
            data = _fetch_answer_groups_json(course_id, question_id)
        except AuthError as e:
            return f"Authentication error: {e}"
        except ValueError as e:
            return f"Error: {e}"
        except Exception as e:
            return f"Error fetching answer groups: {e}"
    
        groups = data.get("groups", [])
        submissions = data.get("submissions", [])
        question = data.get("question", {})
        status = data.get("status", "unknown")
    
        # Count submissions per group
        group_counts: dict[int, dict[str, int]] = {}
        for sub in submissions:
            gid = sub.get("confirmed_group_id") or sub.get("unconfirmed_group_id")
            if gid is not None:
                if gid not in group_counts:
                    group_counts[gid] = {"total": 0, "graded": 0}
                group_counts[gid]["total"] += 1
                if sub.get("graded"):
                    group_counts[gid]["graded"] += 1
    
        # Count ungrouped
        ungrouped = [
            s for s in submissions
            if not s.get("confirmed_group_id") and not s.get("unconfirmed_group_id")
        ]
    
        if output_format == "json":
            result = {
                "question_id": question_id,
                "question_title": question.get("numbered_title", ""),
                "assisted_grading_type": question.get("assisted_grading_type"),
                "status": status,
                "num_groups": len(groups),
                "num_submissions": len(submissions),
                "num_ungrouped": len(ungrouped),
                "groups": [],
            }
            for g in groups:
                gid = g["id"]
                counts = group_counts.get(gid, {"total": 0, "graded": 0})
                result["groups"].append({
                    "id": str(gid),
                    "title": g.get("title", ""),
                    "size": counts["total"],
                    "graded": counts["graded"],
                    "hidden": g.get("hidden", False),
                    "question_type": g.get("question_type", ""),
                })
            return json.dumps(result, indent=2)
    
        # Markdown output
        ag_type = question.get('assisted_grading_type')
        # Resolve type: use assisted_grading_type first, fall back to per-group types
        if not ag_type and groups:
            group_types = {g.get('question_type', '') for g in groups if g.get('question_type')}
            ag_type = ', '.join(sorted(group_types)) if group_types else None
        ag_type_display = ag_type or '(not set)'
        group_word = 'group' if len(groups) == 1 else 'groups'
        lines = [
            f"## Answer Groups — {question.get('numbered_title', question_id)}",
            f"**Type:** {ag_type_display}",
            f"**Status:** {status}",
            f"**Total:** {len(submissions)} submissions across {len(groups)} {group_word}"
            + (f" + {len(ungrouped)} ungrouped" if ungrouped else ""),
            "",
            "| # | Group ID | Title | Type | Size | Graded | Hidden |",
            "|---|----------|-------|------|------|--------|--------|",
        ]
    
        for i, g in enumerate(groups, 1):
            gid = g["id"]
            counts = group_counts.get(gid, {"total": 0, "graded": 0})
            title = g.get("title", "(untitled)")
            # Truncate long LaTeX titles
            if len(title) > 60:
                title = title[:57] + "..."
            g_type = g.get("question_type", "") or ""
            hidden = "🙈" if g.get("hidden") else ""
            graded_str = f"{counts['graded']}/{counts['total']}"
            lines.append(
                f"| {i} | `{gid}` | {title} | {g_type} | {counts['total']} | {graded_str} | {hidden} |"
            )
    
        if ungrouped:
            lines.append(f"\n**Ungrouped:** {len(ungrouped)} submissions need manual grouping")
    
        return "\n".join(lines)

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/Yuanpeng-Li/gradescope-mcp'

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