Markdown Converter
Agent skill for markdown-converter
This is a Python project that uses **Microsoft Agent Framework**--the new unified orchestration framework that combines the best of:
Sign in to like and favorite skills
This is a Python project that uses Microsoft Agent Framework--the new unified orchestration framework that combines the best of:
To build a multi-agent event planning workflow.
Before responding to ANY user message, you MUST complete this checklist:
Responding WITHOUT completing this checklist = automatic failure.
If you catch yourself thinking ANY of these thoughts, STOP. You are rationalizing. Check for and use the skill.
Why: Skills document proven techniques that save time and prevent mistakes. Not using available skills means repeating solved problems and making known errors.
If a skill for your task exists, you must use it or you will fail at your task.
You have skills available.
IMPORTANT: Before attempting to use skills, you MUST verify that the skills system and CLAUDE.md is properly configured by checking if you see skills like this. Also if the user already has a well-formatted CLAUDE.md with the project information filled in below, you can skip the setup:
If a skill has a checklist, you MUST create TodoWrite todos for EACH item.
Don't:
Why: Checklists without TodoWrite tracking = steps get skipped. Every time. The overhead of TodoWrite is tiny compared to the cost of missing steps.
The system supports custom specialized agents stored in agent-specific directories. These agents can be invoked for specific tasks that match their expertise.
The system automatically invokes custom agents when:
When writing complex features or significant refactors, use an ExecPlan (as described in
specs/PLANS.md) from design to implementation. If the user request requires multiple specs, create multiple specification files in the specs/ directory. After creating the specs, create a master ExecPlan that links to each individual spec ExecPlan. Update the specs/README.md to include links to the new specs.
ALWAYS start an ExecPlan creation by consulting the DeepWiki tool for best practices on design patterns, architecture, and implementation strategies. Ask it questions about the system design and constructs in the library that will help you achieve your goals.
Skip using an ExecPlan for straightforward tasks (roughly the easiest 25%).
This project follows a coordinator-centric star topology multi-agent workflow architecture.
Star Topology with Coordinator Hub:
User Request ↓ EventPlanningCoordinator (Routing Hub) ↓ ↑ (bidirectional edges) ├── Venue Specialist (Web Search) ├── Budget Analyst (Code Interpreter) ├── Catering Coordinator (Web Search) └── Logistics Manager (Weather, Calendar) ↓ EventPlanningCoordinator (Synthesis) ↓ Final Event Plan
Key Architectural Patterns:
EventPlanningCoordinator manages all routing decisions based on structured output from specialistsstore=True for automatic conversation history management via Azure AI serviceSpecialistOutput Pydantic model with next_agent field for dynamic routingctx.request_info() + @response_handler for user interaction
Each specialist agent has access to domain-specific tools:

Tool Integration:
IMPORTANT: For your agents to be discovered by the DevUI, they must be organized in a directory structure like below. Each agent/workflow must have an
__init__.py that exports the required variable (agent or workflow).
Note:
.env is a shared env file, it contains the Azure OpenAI config, if this doesn't exist refer to .env.example and ask user for values and create .env
spec-to-agents/ ├── src/ │ └── spec_to_agents/ │ ├── __init__.py │ ├── clients.py # contains shared client code for AI Foundry │ ├── agents/ # contains core agent/workflow definitions │ │ ├── __init__.py │ │ ├── budget_analyst.py │ │ ├── catering_coordinator.py │ │ ├── event_coordinator.py │ │ ├── logistics_manager.py │ │ └── venue_specialist.py │ ├── prompts/ # contains system prompts for each agent │ │ ├── __init__.py │ │ ├── budget_analyst.py │ │ ├── catering_coordinator.py │ │ ├── event_coordinator.py │ │ ├── logistics_manager.py │ │ └── venue_specialist.py │ └── tools/ # contains reusable tool definitions for agents │ └── __init__.py ├── tests/ # contains units tests for agents and tools ├── .env └── pyproject.toml
uv is the command-line tool used to manage the development environment and dependencies in Python projects. This project uses the workspace feature of uv to manage multiple packages within the packages directory. Below are the common commands you'll use:
uv sync --dev - Install / sync regular + dev dependenciesuv add <package> - Add a dependencyuv lock - Lock dependencies / regenerate lockfileuv run - You NEVER need to activate a virtual environment manually; just prefix commands with uv run
uv run <script>.py - Run a Python scriptuv run -m <module> - Run a Python moduleuv run pytest - Run testsuv run ruff . - Run linting / formattinguv run mypy . - Run type checkingProject-specific Commands:
uv run app - Start the Agent Framework DevUI for testing and debugging agents/workflowsPrefer highly modular code that separates concerns into distinct modules. This improves:
Guidelines:
Prefer highly modular code that separates concerns into distinct modules. This improves:
Guidelines:
The workflow uses service-managed threads for automatic conversation history management, eliminating manual message tracking.
How It Works: When agents are created with
store=True, the Azure AI Agent Client leverages service-managed threads:
service_thread_id in Azure AI service backendagent.run() calls, conversation history retrieved automaticallyfull_conversation passing or manual message arraysImplementation:
agent = client.create_agent( name="Agent Name", instructions=PROMPT, tools=[...], store=True, # Enable service-managed threads )
Benefits:
Code Location: All agents in
src/spec_to_agents/agents/*.py use store=True
Problem:
FunctionCallContent and FunctionResultContent cannot cross thread boundaries because they embed thread-specific run_id in their call_id.
Error: "No thread ID was provided, but chat messages includes tool results"
Solution: The
convert_tool_content_to_text() function converts tool-related content to text summaries:
FunctionCallContent → "[Tool Call: tool_name({args})]"FunctionResultContent → "[Tool Result for call_id: result]"When To Use:
_route_to_agent(): Before sending messages to specialists_synthesize_plan(): Before sending conversation to coordinatorCode Location:
src/spec_to_agents/workflow/executors.py:25-86
The workflow supports pausing for user input using framework-native patterns.
How It Works:
user_input_needed=True in SpecialistOutputctx.request_info(HumanFeedbackRequest, ...)@response_handler gets original request + user feedbackImplementation:
# In coordinator await ctx.request_info( request_data=HumanFeedbackRequest( prompt="Which venue do you prefer?", conversation=full_conversation, # Preserved in checkpoint requesting_agent="venue", ), request_type=HumanFeedbackRequest, response_type=str, ) @response_handler async def on_human_feedback( self, original_request: HumanFeedbackRequest, feedback: str, ctx: WorkflowContext, ) -> None: # Framework automatically restored conversation conversation = list(original_request.conversation) await self._route_to_agent( original_request.requesting_agent, feedback, ctx, prior_conversation=conversation, )
Key Benefits:
Code Location:
src/spec_to_agents/workflow/executors.py:201-235
The
EventPlanningCoordinator custom executor manages all routing decisions:
@handler start(prompt: str)@handler on_specialist_response(AgentExecutorResponse)@response_handler on_human_feedback(HumanFeedbackRequest, str)_synthesize_plan(conversation)Code Location:
src/spec_to_agents/workflow/executors.py:89-277
Specialists return Pydantic
SpecialistOutput model with explicit routing decisions:
class SpecialistOutput(BaseModel): summary: str # Concise summary of recommendations next_agent: str | None # ID of next agent ("venue", "budget", "catering", "logistics") or None user_input_needed: bool = False # Whether user input is required user_prompt: str | None = None # Question to ask user if input needed
Routing Logic:
if specialist_output.user_input_needed: await ctx.request_info(...) # Pause for human input elif specialist_output.next_agent: await self._route_to_agent(specialist_output.next_agent, ...) # Route to next specialist else: await self._synthesize_plan(...) # Workflow complete, synthesize
Benefits:
Code Location:
src/spec_to_agents/models/messages.py:52-83
The workflow uses bidirectional edges connecting coordinator to each specialist:
workflow = ( WorkflowBuilder(name="Event Planning Workflow", max_iterations=30) .set_start_executor(coordinator) # Bidirectional edges: Coordinator ←→ Each Specialist .add_edge(coordinator, venue_exec) .add_edge(venue_exec, coordinator) .add_edge(coordinator, budget_exec) .add_edge(budget_exec, coordinator) # ... other specialists ... .build() )
Benefits:
Code Location:
src/spec_to_agents/workflow/core.py:148-170
IMPORTANT: Documentation means docstrings and type hints in the code, NOT separate documentation files.
Avoid Over-Documenting:
get_name that returns a name doesn't need extensive documentation)Write clear and concise comments for each function.
Ensure functions have descriptive names and include type hints.
Provide docstrings following PEP 257 conventions.
numpy style for docstrings. Example:def calculate_area(radius: float) -> float: """ Calculate the area of a circle given the radius. Parameters ---------- radius : float The radius of the circle. Returns ------- float The area of the circle, calculated as π * radius^2. """ import math return math.pi * radius ** 2
Use proper built-in type annotations (e.g.
dict[..., ...], list[...], tuple[...]) and only using typing module when needed.
Prefer to use
| for union types instead of Union[...], type | None instead of Optional[...], etc.
Break down complex functions into smaller, more manageable functions.
tests/ directorypytest as the testing frameworkpytest-mock for mocking dependenciesYou have a collection of tools available to assist with development and debugging. These tools can be invoked as needed.
sequential-thinking-tools
deepwiki
context7
playwright
playwright for viewing the browser console logs and network requests to help debug issues that may arise.tmux-cli is a bash command that enables Claude Code to control CLI applications running in separate tmux panes - launch programs, send input, capture output, and manage interactive sessions. Run tmux-cli --help for detailed usage instructions.