A command-line interface for interacting with the Grok-3 model with banking function calling support.
- Function Calling: Supports calling predefined banking functions through natural language
- Account Management: List and filter checking and savings accounts
- Transaction History: View and filter transaction history across all accounts
- Payee Management: List and manage payees for payments
- Payment Processing: Make payments from accounts to registered payees
- Fund Transfers: Transfer money between your own accounts
- Balance Inquiries: Get current balances and account summaries
- Chat History: Automatically saves conversation history with timestamps
- Streaming Support: Real-time response streaming for better user experience
- Extensible Architecture: Easy to add new banking functions with automatic discovery
-
Configure API Key:
cd CLI dotnet user-secrets init dotnet user-secrets set GrokApi:ApiKey <your-grok-api-key>
-
Build and Run:
dotnet build dotnet run
- Type your questions naturally
- Type
functionsto see available functions - Type
exitto quit
Account Management:
- "Show me all my accounts"
- "List only my checking accounts"
- "What are my savings accounts?"
Balance Inquiries:
- "What's my account balance?"
- "Show me the balance for my checking account"
- "Give me a summary of all my account balances"
Transaction History:
- "Show me my recent transactions"
- "List transactions for my checking account"
- "Show me all payments from last month"
- "What transfers did I make this week?"
Payee Management:
- "List all my payees"
- "Show me payees with 'Electric' in the name"
- "Who can I pay?"
Payment Processing:
- "Pay $125.50 to Electric Company from my checking account"
- "Make a payment to John Doe for $50"
- "Pay my internet bill"
Fund Transfers:
- "Transfer $500 from checking to savings"
- "Move $1000 to my vacation fund"
- "Transfer money between accounts"
The application includes pre-loaded mock banking data:
Accounts:
- Primary Checking (acc-001): $2,500.75
- Emergency Savings (acc-002): $15,000.00
- Vacation Fund (acc-003): $3,250.50
Payees:
- Electric Company
- Internet Service Provider
- Rent Management Company
- John Doe
Transaction History:
- Sample transactions including deposits, payments, and transfers
- All new transactions are kept in memory during the session
- Data resets when the application restarts
The application provides 6 core banking functions:
- list_accounts: List and filter bank accounts by type
- get_account_balance: Get balance information and recent transactions
- list_transactions: View and filter transaction history with multiple criteria
- list_payees: List and search registered payees
- make_payment: Process payments from accounts to payees
- transfer_funds: Transfer money between your own accounts
The application uses appsettings.json for configuration:
{
"GrokApi": {
"BaseUrl": "https://api.x.ai/v1/",
"Model": "grok-3",
"MaxTokens": 4000,
"Temperature": 0.7
},
"ChatSettings": {
"MaxHistoryLength": 50,
"AutoSaveHistory": true,
"LogsDirectory": "logs",
"HistoryFilePrefix": "chat_history"
}
}The application follows a clean architecture pattern with clear separation of concerns:
- Core/Abstractions/: Base classes and interfaces
FunctionBase.cs: Abstract base class for function implementationsIFunction.cs: Function interface and attribute definitions
- Core/Models/: Pure data models and DTOs
ChatModels.cs: Chat-related data models (Message, ChatMessage, ChatHistory)FunctionModels.cs: Function-related data models (FunctionDefinition, ToolCall, etc.)
- Core/Settings/: Configuration classes
GrokApiSettings.cs: API configuration settingsChatSettings.cs: Chat behavior configuration
- Core/Services/: Core business services
ChatService.cs: Manages conversation history and persistenceFunctionDiscoveryService.cs: Discovers and loads function implementations
- Core/Handlers/: Request/response handlers
FunctionHandler.cs: Manages function execution and registration
- Core/Infrastructure/: Infrastructure concerns
Http/GrokApiClient.cs: Handles API communication with function calling supportDependencyInjection/ServiceConfigurator.cs: Service registration and DI setup
- Domain/Functions/: Banking function implementations
ListAccountsFunction.cs: List and filter bank accountsGetAccountBalanceFunction.cs: Get account balances and summariesListTransactionsFunction.cs: View and filter transaction historyListPayeesFunction.cs: List and search payeesMakePaymentFunction.cs: Process payments to payeesTransferFundsFunction.cs: Transfer money between accounts
- Domain/Models/: Banking domain models
BankingModels.cs: Account, Transaction, and Payee models
- Domain/Services/: Banking business services
BankingDataService.cs: In-memory banking data managementBankingServiceProvider.cs: Singleton service provider
- Program.cs: Main application entry point with interactive chat loop
The application uses automatic function discovery to load all valid functions from the Domain/Functions/ directory. Functions are automatically discovered when they:
- Implement the
IFunctioninterface or inherit fromFunctionBase - Are decorated with the
[Function]attribute - Have
IsEnabled = truein the Function attribute (default) - Are located in the Functions directory or in the main assembly
Follow these steps to create a new banking function:
Create a new .cs file in Domain/Functions/ that inherits from FunctionBase:
[Function("your_banking_function", "Description of banking operation")]
public class YourBankingFunction : FunctionBase
{
private readonly IBankingDataService _bankingService;
public YourBankingFunction(IBankingDataService bankingService)
{
_bankingService = bankingService;
}
public YourBankingFunction() : this(BankingServiceProvider.Instance) { }
public override async Task<string> ExecuteAsync(string arguments)
{
try
{
var args = JsonConvert.DeserializeObject<YourFunctionArgs>(arguments);
if (args == null) return "Invalid arguments";
// Your banking logic here using _bankingService
var result = new { /* your result object */ };
return JsonConvert.SerializeObject(result, Formatting.Indented);
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
}
private class YourFunctionArgs
{
[JsonProperty("account_id")]
[FunctionParameter("Account ID for the operation", IsRequired = true)]
public string AccountId { get; set; } = string.Empty;
[JsonProperty("amount")]
[FunctionParameter("Transaction amount")]
public decimal? Amount { get; set; }
}
}The FunctionParameter attribute supports these properties:
- Description: Required. Describes what the parameter does.
- IsRequired: Optional. Set to
trueif the parameter is required. - EnumValues: Optional. Array of allowed string values for the parameter.
- Build the project:
dotnet build - Run the application:
dotnet run - Type
functionsin the chat to see your new function listed - Test your function by asking the agent to use it in natural language
- Error Handling: Always wrap your function logic in try-catch blocks
- Validation: Validate input arguments before processing
- Return Format: Return JSON-serialized objects for structured data
- Async Operations: Use async/await for I/O operations
- Documentation: Use clear descriptions in the Function and FunctionParameter attributes
- Parameter Naming: Use lowercase with underscores for JSON property names to match common API conventions
See the following banking functions in the Domain/Functions/ directory:
- ListAccountsFunction.cs: Lists and filters bank accounts by type
- GetAccountBalanceFunction.cs: Gets account balances and recent transactions
- ListTransactionsFunction.cs: Views and filters transaction history
- ListPayeesFunction.cs: Lists and searches registered payees
- MakePaymentFunction.cs: Processes payments from accounts to payees
- TransferFundsFunction.cs: Transfers money between accounts
To deploy a new function to an existing installation:
- Compile your function into a separate assembly (DLL)
- Copy the DLL to the Functions directory of the deployed application
- Restart the application - the function will be automatically discovered and loaded
This plugin architecture allows for easy extension of the agent's capabilities without modifying the core codebase. The FunctionBase class provides automatic parameter discovery using reflection, so you only need to focus on implementing the business logic.
CLI/
├── Core/ # Core application components
│ ├── Abstractions/ # Base classes and interfaces
│ ├── Models/ # Pure data models and DTOs
│ ├── Settings/ # Configuration classes
│ ├── Services/ # Core business services
│ ├── Handlers/ # Request/response handlers
│ └── Infrastructure/ # Infrastructure concerns
│ ├── Http/ # HTTP clients and API communication
│ └── DependencyInjection/ # Service registration
├── Domain/ # Domain-specific implementations
│ ├── Functions/ # Banking function implementations
│ ├── Models/ # Banking domain models
│ └── Services/ # Banking business services
├── logs/ # Chat history files
├── appsettings.json # Application configuration
└── Program.cs # Application entry point
Chat history is automatically saved to the logs/ directory with timestamped filenames.
The application uses the following banking data model:
- Checking: Day-to-day transaction accounts
- Savings: Interest-bearing savings accounts
- Deposit: Money added to an account
- Withdrawal: Money removed from an account
- Transfer: Money moved between accounts
- Payment: Money sent to a payee
- All banking data is stored in memory and resets on application restart
- New transactions created during the session are preserved until restart
- Chat history is persisted to disk in the
logs/directory
- Account numbers are masked (e.g., ****1234)
- No actual banking integration - purely simulated for demonstration
- All data is local and not transmitted anywhere except to the Grok API for processing
Each banking function accepts specific parameters:
account_type(optional): "checking" or "savings"
account_id(optional): Specific account ID, or omit for all accounts
account_id(optional): Filter by accounttransaction_type(optional): "deposit", "withdrawal", "transfer", "payment"start_date(optional): Start date (YYYY-MM-DD)end_date(optional): End date (YYYY-MM-DD)limit(optional): Maximum number of results
name_filter(optional): Search by payee name
from_account_id(required): Source account IDpayee_id(required): Target payee IDamount(required): Payment amountdescription(optional): Payment description
from_account_id(required): Source account IDto_account_id(required): Destination account IDamount(required): Transfer amountdescription(optional): Transfer description
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License is a permissive license that allows for reuse within proprietary software provided that all copies of the licensed software include a copy of the MIT License terms and the copyright notice.