👗 TrendMate

Source Code — Malaysian Fashion Seller Research Assistant

📁 File Structure

projects/trendmate/
  ├── app.py— CLI terminal version of the research assistant
  ├── web_app.py— Streamlit web interface (main app)
  ├── system-prompt.txt— Agent persona, Malaysian fashion focus, 3-sentence format rules
  ├── requirements.txt— Python dependencies
  ├── .env.example— API key template
  ├── demo.html— Static interactive demo page
  ├── user-guide.md— Plain language setup and usage guide
  ├── problem-statement.md— Problem definition and target users
  └── project-outline.md— App name, features, tech stack, roadmap

🔑 Key Code: Agent Loop (web_app.py)

TrendMate uses the same ReAct loop as MyPropLex — Claude decides what to search, calls Tavily, reads results, and iterates. The difference is the system prompt which steers Claude toward Malaysian fashion market sources and forces actionable, market-specific answers.

def run_agent(user_message, history, client, tavily, system_prompt): # Add user message to conversation history history.append({"role": "user", "content": user_message}) while True: # Call Claude with search tool available response = client.messages.create( model="claude-sonnet-4-6", max_tokens=2048, system=system_prompt, tools=TOOLS, messages=history ) if response.stop_reason == "end_turn": # Claude is done — return the answer text = "\n".join(b.text for b in response.content if hasattr(b, "text")) history.append({"role": "assistant", "content": response.content}) return text elif response.stop_reason == "tool_use": # Claude wants to search — run Tavily and feed results back history.append({"role": "assistant", "content": response.content}) tool_results = [] for block in response.content: if block.type == "tool_use" and block.name == "search_web": tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": search_web(block.input["query"], tavily) }) history.append({"role": "user", "content": tool_results})

🔑 Key Code: System Prompt (system-prompt.txt)

The system prompt is what makes TrendMate a fashion specialist instead of a general chatbot. It tells Claude exactly which sources to prioritise, what format to use, and how to make every answer actionable for a Malaysian seller.

HOW YOU ANSWER 1. Search for the latest information before answering. Fashion moves fast — always find current data. 2. Give actionable, specific recommendations. Not just "baju kurung is trending" but "baju kurung moden in pastel colours is trending for Raya 2025, priced between RM89–RM149 on Shopee." 3. When talking about prices, always mention the Malaysian market specifically. FORMAT OF YOUR ANSWERS - Maximum 3 sentences per answer. No exceptions. - Sentence 1: Direct finding or recommendation (specific: product type, platform, price range). - Sentence 2: One piece of evidence (trending on TikTok, top-selling on Shopee, sourcing tip). - Sentence 3: One action the seller should take right now, or a timing note.

🔑 Key Code: Preset Questions in Sidebar

Preset questions are displayed as clickable sidebar buttons. When clicked, the question is set in session state and processed on the next render cycle — the same flow as typing a question manually.

# In sidebar — render preset buttons for i, q in enumerate(PRESET_QUESTIONS): if st.button(f"{i+1}. {q}", key=f"q{i}", use_container_width=True): st.session_state.pending_q = q # Store for next render # In main area — check for pending question or typed input prompt = None if st.session_state.pending_q: prompt = st.session_state.pending_q st.session_state.pending_q = None # Clear immediately elif q := st.chat_input("Type your fashion market question..."): prompt = q if prompt: # Process the question — same path for preset and typed answer = run_agent(prompt, st.session_state.conv_history, ...)

📦 Dependencies (requirements.txt)

anthropic>=0.40.0 # Claude API SDK tavily-python>=0.3.0 # Web search API python-dotenv>=1.0.0 # Load .env files locally streamlit>=1.32.0 # Web interface framework