Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions kits/sporting-director/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LAMATIC_API_KEY=your_lamatic_api_key_here
LAMATIC_ENDPOINT=your_lamatic_flow_endpoint_here
LAMATIC_FLOW_ID=cfaf6f71-033c-4ad2-abc6-3ae77158097f
LAMATIC_PROJECT_ID=11727d21-0009-4e68-a4f3-c891a54f1baf

4 changes: 4 additions & 0 deletions kits/sporting-director/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.lamatic/
node_modules/
.env*
!.env.example
58 changes: 58 additions & 0 deletions kits/sporting-director/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# sporting-director

AI-powered decision-support assistant for football sporting directors and recruitment teams. Given a target player and buying club context, it searches for real, current information and generates a structured transfer feasibility report — helping directors quickly assess whether a target is realistic before investing research time.

## What it does

Instead of manually researching a player across news sites, transfer trackers, relying on scouts and rumor mills, a sporting director provides:
- Player name
- Buying club
- Available budget
- Club's positional/tactical need

The agent searches for recent, real information about the player and returns a structured report covering:
1. **Transfer Feasibility Score** (1-10) with justification
2. **Tactical Fit Summary** — how the player suits the club's needs
3. **Personal/Cultural Fit** — rivalries, boyhood club ties, public statements, if evidenced
4. **Competing Interest** — other clubs reportedly in the race
5. **Additional Intel** — agent, valuation, form, contract terms, if available
6. **Key Risks** — contractual, financial, fitness, or behavioral
7. **Alternative Targets** — suggested if feasibility is low

The agent only reports facts found in search results — it does not invent statistics, quotes, or rivalries. When information isn't available, it says so explicitly.

## Setup

1. Clone this repo and navigate to `kits/sporting-director/apps/`
2. Copy `.env.example` to `.env.local` and fill in your Lamatic API key and flow endpoint
3. Install dependencies: `npm install`
4. Run locally: `npm run dev`

## Flow architecture
Comment thread
KishoharS marked this conversation as resolved.

API Request (playerName, buyingClub, budget, needs)
→ Web Search (recent news/info about the player)
→ Generate Text (structured feasibility report)
→ API Response

See `flows/sporting-director.ts` for the full flow definition and `agent.md` for the agent contract.

## Example

**Input:** Player: Neymar, Buying Club: Real Madrid, Budget: €5M, Needs: high-profile signing

**Output:** Feasibility score of 1/10 — flags his active Santos contract through Dec 2026, budget mismatch, and recent injury/fitness concerns, with a note on Barcelona rivalry history.

## Who this is for

This tool is best suited for **low and mid-tier clubs** with limited scouting budgets and research staff. Top-tier clubs typically have dedicated recruitment departments, proprietary scouting networks, and data providers (e.g. Wyscout, StatsBomb) that already outperform what public search can surface, for them, this is a supplementary sanity-check at best, not a primary tool.

For resource-constrained clubs, it compresses hours of manual research (checking transfer sites, news, forums) into a single structured report, freeing up staff time for outreach and negotiation instead of information-gathering.

## Limitations

- Market valuation, agent representation, and negotiation data depend on what's publicly searchable — not always available
- Search results are limited to the last 30 days by default, which may miss older but relevant context
- This is a research aid, not a replacement for professional scouting or due diligence
- Reports are based on publicly available search results, which lag behind real-time information that agents, insiders, or larger clubs' networks may already have. Decision-makers should treat this as a starting point for research, not a final or time-sensitive signal — act quickly once a target is identified, since competing interest may already be ahead in negotiations
- Not a substitute for direct scouting network intelligence available to well-resourced clubs
22 changes: 22 additions & 0 deletions kits/sporting-director/agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Sporting Director

## Overview
Comment thread
KishoharS marked this conversation as resolved.

Sporting Director is a decision-support assistant for football recruitment teams. Given a target player and buying club context, it searches for real, current information about the player and generates a structured feasibility report — helping sporting directors quickly assess whether a transfer target is realistic before committing research time.

## Flow

1. **API Request** — accepts `playerName`, `buyingClub`, `budget`, and `needs` (club's positional/tactical need)
2. **Web Search** — searches for recent news, transfer rumors, and player information (last 30 days)
3. **Generate Text** — analyzes search results and produces a structured report: transfer feasibility score, tactical fit, personal/cultural fit, competing interest, key risks, and alternative targets
4. **API Response** — returns the report as structured JSON

## Guardrails

- The agent only uses facts present in search results — it does not invent statistics, quotes, or rivalries
- When information is unavailable, the report explicitly states so rather than speculating
- Output follows a concise, scannable executive-briefing style suitable for time-constrained decision-makers

## Integration

Call the flow's API endpoint with the four required inputs. See README.md for setup and usage details.
4 changes: 4 additions & 0 deletions kits/sporting-director/apps/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LAMATIC_API_KEY=your_lamatic_api_key_here
LAMATIC_ENDPOINT=your_lamatic_flow_endpoint_here
LAMATIC_FLOW_ID=cfaf6f71-033c-4ad2-abc6-3ae77158097f
LAMATIC_PROJECT_ID=11727d21-0009-4e68-a4f3-c891a54f1baf
42 changes: 42 additions & 0 deletions kits/sporting-director/apps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
38 changes: 38 additions & 0 deletions kits/sporting-director/apps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Sporting Director App

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
67 changes: 67 additions & 0 deletions kits/sporting-director/apps/actions/orchestrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use server";

import { lamatic, FLOW_ID } from "@/lib/lamatic-client";

export type ScoutResult = {
report: string;
};

export type ScoutActionResult =
| { success: true; data: ScoutResult }
| { success: false; error: string };

export async function generateReport(
playerName: string,
buyingClub: string,
budget: string,
needs: string
): Promise<ScoutActionResult> {

const requiredValues = [playerName, buyingClub, budget, needs];
if (
requiredValues.some(
(value) => typeof value !== "string" || !value.trim()
)
) {
Comment thread
KishoharS marked this conversation as resolved.
return {
success: false,
error: "Player name, buying club, budget, and club needs are required"
}
}

try {
const response = await lamatic.executeFlow(FLOW_ID, {
playerName,
buyingClub,
budget,
needs,
});

if (response.status !== "success") {
return {
success: false,
error:
typeof response.message === "string" && response.message
? response.message
: "The workflow could not process this request.",
};
}

if (!response.result) {
return { success: false, error: "The workflow returned no result." };
}

const raw = response.result as { report?: string };
if (!raw.report || !raw.report.trim()){
return { success: false, error: "The workflow returned an empty report."};
}
return { success: true, data: { report: raw.report }};

} catch {
console.error("generateReport failed while executing the Lamatic workflow.");
return {
success: false,
error: "Could not reach the Lamatic workflow. Please try again.",
};
}
}
Binary file added kits/sporting-director/apps/app/favicon.ico
Binary file not shown.
50 changes: 50 additions & 0 deletions kits/sporting-director/apps/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@import "tailwindcss";

:root {
--background: #ffffff;
--foreground: #171717;

/* Sporting Director Component Palette */
--overlay-start: rgb(0 0 0 / 0.4);
--overlay-mid: rgb(0 0 0 / 0.5);
--overlay-end: rgb(0 0 0 / 0.7);

--surface-bg: rgb(255 255 255 / 0.1);
--surface-border: rgb(255 255 255 / 0.2);
--surface-border-focus: rgb(255 255 255 / 0.5);

--text-primary: #ffffff;
--text-body: rgb(255 255 255 / 0.9);
--text-secondary: rgb(255 255 255 / 0.8);
--text-muted: rgb(255 255 255 / 0.6);
--text-placeholder: rgb(255 255 255 / 0.4);

--btn-bg: #ffffff;
--btn-bg-hover: rgb(255 255 255 / 0.9);
--btn-text: #111827;

--error-bg: rgb(69 10 10 / 0.4);
--error-border: rgb(248 113 113 / 0.3);
--error-text: rgb(252 165 165);
--error-text-alt: rgb(254 202 202);
}

@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}

@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}

body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}
33 changes: 33 additions & 0 deletions kits/sporting-director/apps/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});

const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});

export const metadata: Metadata = {
title: "Agent Hunt",
description: "AI Sporting Director - transfer feasibility briefings",
};
Comment thread
KishoharS marked this conversation as resolved.

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
</html>
);
}
Loading
Loading